J'ai un UIScrollView
avec un autre UIScrollView
à l'intérieur. Ils défilent tous les deux horizontalement et ont pagingEnabled = YES
. Supposons que j'ai commencé à faire défiler la vue de défilement interne et atteint la limite la plus à droite. Et si je continue à y faire défiler, alors le scrollView externe commence à se déplacer. Je dois éviter cela. La vue intérieure doit sauter avec effet élastique, l'extérieur doit rester à sa place.
J'espère que c'est clair, mais voici un croquis:
J'ai essayé de définir outerView.scrollEnabled = NO;
comme ça:
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
outerView.scrollEnabled = NO;
}
, et cela fonctionne exactement comme j'ai besoin, si vous souhaitez faire défiler uniquement dans innerView. OuterView ne défile plus. Mais je dois redéfinir scrollEnabled
sur YES quelque part pour le cas si je veux faire défiler la vue externe à nouveau. J'ai essayé de le faire ici:
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
outerView.scrollEnabled = YES;
}
, mais j'obtiens le même problème: après avoir atteint la limite la plus à droite des scrolls innerView externalView au lieu des sauts innerView avec effet élastique.
Des suggestions pour résoudre un problème?
MISE À JOUR
Cette solution fonctionne toujours:
@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
---------------------------------------------- -------------------------
ANCIENNE RÉPONSE: ne fonctionne pas toujours
Voici comment j'ai résolu le problème:
@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;
}
Si je comprends bien, self.delaysContentTouches = NO;
Fait que tous les événements doivent être livrés immédiatement, et - (BOOL)touchesShouldBegin:(NSSet *)touches withEvent:(UIEvent *)event inContentView:(UIView *)view
empêche le passage de ces événements par la chaîne de répondeur.
Modifiez vos méthodes de la manière suivante:
- (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;
}
}
}
J'ai un problème similaire. J'ai trouvé la solution, mais cela ne fonctionne qu'avec 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
Cela fonctionne bien pour moi:
- (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];
}
N'oubliez pas d'adopter UIScrollViewDelegate dans votre déclaration de classe et de définir le délégué de innerScrollView sur self (n'affectez PAS le délégué de externalScrollView)