2013-03-15 15 views
23

Mam UIScrollView z innym UIScrollView wewnątrz. Oba są przewijane poziomo i mają pagingEnabled = YES. Załóżmy, że zacząłem przewijać wewnętrzny widok przewijania i osiągnąłem najbardziej prawe ograniczenie. A jeśli przejdę dalej, przewijam zewnętrzny scrollView. Muszę tego uniknąć. Wewnętrzny widok powinien skakać z efektem gumki, zewnętrzny powinien pozostać w swoim miejscu.UIScrollView inside UIScrollView

nadzieję, że to jasne, ale o to szkic: enter image description here

Próbowałem ustawić outerView.scrollEnabled = NO; tak:

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

i działa dokładnie tak, jak trzeba, jeśli przewijać tylko w innerView. OuterView nie jest już przewijany. Ale muszę ustawić scrollEnabled z powrotem na TAK dla przypadku, gdybym chciał ponownie przewinąć widok zewnętrzny. Próbowałem to zrobić tutaj:

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

, ale nie dostaję ten sam problem: po osiągnięciu najbardziej prawo związane z innerView outerView przewija zamiast innerView skoki ze skutkiem gumy-band.

Wszelkie sugestie, jak rozwiązać problem?

+0

w metodach delegowania przeglądania przewijania nie wygląda jak sprawdzanie, który scrollviewViewBeginDragging i który scrollViewDidEndDecelerating. Nie rozumiem w pełni twoich potrzeb, ale to jest złe. – mkral

+0

spróbuj ustawić znacznik w każdym przewijanym widoku, a następnie zaznacz 'if (scrollview.tag == 1) ' – mkral

+0

@mkral: Mam różne delegacje dla tych widoków, więc nie muszę sprawdzać parametru. – Anastasia

Odpowiedz

17

UPDATE

To rozwiązanie działa zawsze:

@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 ODPOWIEDŹ: nie działa zawsze

Oto jak rozwiązać ten problem:

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

Jak rozumiem, self.delaysContentTouches = NO; czyni wszystkie zdarzenia mają być dostarczone natychmiast, a - (BOOL)touchesShouldBegin:(NSSet *)touches withEvent:(UIEvent *)event inContentView:(UIView *)view uniemożliwia przekazywanie tych wydarzeń przez łańcuch odpowiadający.

+0

Mam ten sam problem. Próbowałem Twojego rozwiązania, ale w ten sposób blokuje subview InnerView od wszelkich zdarzeń dotyku. Mam kilka przycisków wewnątrz wewnętrznego przewijania jako subviews. Przewijanie działa dobrze, ale przyciski nie są już dostępne. Czy masz inne rozwiązanie? –

+0

@AlexeyGolikov: Tak, to rozwiązanie jest naprawdę trudne i nie jestem pewien, czy to działa w każdym przypadku. Myślę, że sesja WWDC 2013 "Odkrywanie widoków przewijania w iOS 7" (developer.apple.com/wwdc/videos/index.php?id=217) pomogłaby, a mianowicie Demo, która zaczyna się o 11:00. Niestety, widziałem ten film znacznie później, zadałem to pytanie i nie próbowałem go zaimplementować. – Anastasia

+1

Dziękuję, @anastasia. Niestety film mi nie pomógł. Wciąż szukam rozwiązania. –

2

modyfikować swoje metody przez poniższy sposób:

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

Dzięki, ale problem polega na tym, że scrollView ma scrollEnabled == NO; than - (void) scrollViewWillBeginDragging: (UIScrollView *) scrollView nie wymaga już więcej. Więc nie mogę ustawić scrollEnabled z powrotem na TAK w tej metodzie. – Anastasia

2

Działa to dobrze dla mnie:

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

Pamiętaj, aby przyjąć UIScrollViewDelegate w deklaracji klasy i ustawić delegata innerScrollView do siebie (nie należy przypisać delegata outerScrollView)

2

Mam podobny problem. Znalazłem rozwiązanie, ale działa tylko z 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