UIScrollView dentro de UIScrollView


Tengo un UIScrollView con otro UIScrollView dentro. Ambos se desplazan horizontalmente y tienen pagingEnabled = YES. Supongamos que comencé a desplazarme por la vista de desplazamiento interior y alcancé el límite más a la derecha. Y si continúo desplazándome en él, entonces la vista de desplazamiento exterior comienza a moverse. Necesito evitar esto. Vista interior debe saltar con efecto de banda de goma, exterior debe permanecer en su lugar.

Espero que esté claro, pero aquí hay un bosquejo: introduzca la descripción de la imagen aquí

He tratado de establecer outerView.scrollEnabled = NO; así:

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
    outerView.scrollEnabled = NO;
}

, y funciona exactamente como necesito, si para desplazarse solo en innerView. OuterView ya no se desplaza. Pero tengo que configurar scrollEnabled de nuevo a SÍ en algún lugar para el caso si quisiera volver a desplazarme hacia fuera. He tratado de hacerlo aquí:

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
    outerView.scrollEnabled = YES;
}

, pero que estoy recibiendo el mismo problema: después de alcanzar el límite más correcto de Inerview pergaminos outerView en lugar de saltos Inerview con efecto de banda de goma.

Alguna sugerencia de cómo resolver un problema?

Author: julia_v, 2013-03-15

4 answers

ACTUALIZACIÓN

Esta solución funciona siempre:

@implementation InnerScrollViewController <UIScrollViewDelegate, UIGestureRecognizerDelegate>

- (void)viewDidLoad
{
    UISwipeGestureRecognizer*   swipeGesture = [[[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleSwipe:)] autorelease];
    swipeGesture.delegate = self;
    [self.view addGestureRecognizer:swipeGesture];
}

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
    _outerScrollView.scrollEnabled = NO;
    return YES;
}

- (void)handleSwipe:(UIGestureRecognizer*)gestureRecognizer
{

}

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{   
    _outerScrollView.scrollEnabled = NO;
}

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
    if (!decelerate)
    {
        _outerScrollView.scrollEnabled = YES;
    }
}

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
    _outerScrollView.scrollEnabled = YES;
}

@end

-----------------------------------------------------------------------

VIEJA RESPUESTA: no funciona siempre

Así es como resolví el problema:

@implementation InnerView

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        self.delaysContentTouches = NO;
    }
    return self;
}

- (BOOL)touchesShouldBegin:(NSSet *)touches withEvent:(UIEvent *)event inContentView:(UIView *)view
{
    return NO;
}

Según tengo entendido, self.delaysContentTouches = NO; hace que todos los eventos se entreguen inmediatamente, y - (BOOL)touchesShouldBegin:(NSSet *)touches withEvent:(UIEvent *)event inContentView:(UIView *)view previene el paso de estos eventos por la cadena de respuesta.

 18
Author: Anastasia,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-11-29 16:10:11

Modifique sus métodos de la siguiente manera:

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
    if(scrollView == innerView)
        outerView.scrollEnabled = NO;
    else
        outerView.scrollEnabled = YES;
}

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
    if(scrollView == innerView)
    {
         if(innerView.contentOffset.x + innerView.frame.size.width == innerView.contentSize.width)
         {
              outerView.scrollEnabled = NO;
         }
         else
         {
              outerView.scrollEnabled = YES;
         }
    }
}
 2
Author: Apurv,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-03-15 16:48:02

Tengo un problema similar. Encontré la solución, pero solo funciona con innerScrollView.bounces = NO.

@interface PageCtrl ()
    @property (weak, nonatomic) IBOutlet UIScrollView *innerScrollView;
    @property(nonatomic) UIPanGestureRecognizer *panLockScroll;
@end

@implementation PageCtrl
- (void)viewDidLoad {
    // ...
    self.innerScrollView.delegate = self;   

    self.innerScrollView.bounces = NO;   // disable bounces!

    self.panLockScroll = [[UIPanGestureRecognizer alloc]initWithTarget:self action:nil];
    self.panLockScroll.delegate = self;
    [self.innerScrollView addGestureRecognizer:self.panLockScroll];
}

- (BOOL)gestureRecognizer:(UIGestureRecognizer*)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer*)otherGestureRecognizer{
    if( gestureRecognizer == self.panLockScroll && 
        otherGestureRecognizer == self.innerScrollView.panGestureRecognizer ){
        return YES;
    }
    return NO;
}

@end
 2
Author: Eol,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-07-10 20:36:19

Esto funciona bien para mí:

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
  outerScrollView.scrollEnabled = NO;
}

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
  [NSTimer scheduledTimerWithTimeInterval:0.3
                                     target:[NSBlockOperation blockOperationWithBlock:^{ outerScrollView.scrollEnabled = YES; }]
                                   selector:@selector(main)
                                   userInfo:nil
                                    repeats:NO];
}

Recuerde adoptar UIScrollViewDelegate en su declaración de clase y establecer el delegado de innerScrollView en self (no asigne el delegado de outerScrollView)

 1
Author: etayluz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-03-10 00:26:06