Подтвердить что ты не робот

UIScrollView внутри UIScrollView

У меня есть UIScrollView с другим UIScrollView внутри. Оба они прокручиваются по горизонтали и имеют pagingEnabled = YES. Предположим, что я начал прокручивать внутренний вид прокрутки и достиг самой правой границы. И если я продолжу прокрутку в нем, тогда внешний scrollView начнет двигаться. Мне нужно избегать этого. Внутренний вид должен прыгать с резиновым эффектом, внешний должен оставаться на нем.

Надеюсь, что это понятно, но вот эскиз: enter image description here

Я попытался установить outerView.scrollEnabled = NO; следующим образом:

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

и он работает именно так, как мне нужно, если прокручивать только в innerView. OuterView больше не прокручивается. Но я должен установить scrollEnabled назад к YES где-нибудь для случая, если я захочу снова прокрутить внешний вид. Я попытался сделать это здесь:

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

но я получаю ту же проблему: после достижения самой правой границы прокрутки innerView во внешнем виде вместо переходов innerView с эффектом резинкой.

Любые предложения по решению проблемы?

4b9b3361

Ответ 1

UPDATE

Это решение работает всегда:

@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

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

OLD ANSWER: не работает всегда

Вот как я решил проблему:

@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;
}

Как я понимаю, self.delaysContentTouches = NO; позволяет немедленно доставлять все события, а - (BOOL)touchesShouldBegin:(NSSet *)touches withEvent:(UIEvent *)event inContentView:(UIView *)view предотвращает передачу этих событий по цепочке ответчиков.

Ответ 2

Измените методы следующим образом:

- (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;
         }
    }
}

Ответ 3

Это хорошо работает для меня:

- (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];
}

Не забудьте принять UIScrollViewDelegate в объявлении класса и установить делегат из innerScrollView для себя (НЕ назначайте делегат внешнегоScrollView)

Ответ 4

У меня подобная проблема. Я нашел решение, но оно работает только с 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