-->

水平的UIScrollView具有垂直UIScrollViews内部 - 如何防止内周涡旋视图滚动滚

2019-08-02 10:21发布

无法找到一个解决方案。

我建立一个应用程序,与大滚动视图,谁拥有分页(水平)。 这里面滚动视图,还有的UIView的的网格,并且它们中的每一个内部的UIScrollView的,具有垂直滚动视图。

现在,问题是,当我传呼我的“大”滚动视图,有时触摸陷入电网的UIViews内小scrollviews之一。

我不知道如何避免它 - 用则hitTest试图伎俩,但还是没能找到答案。

希望我是清楚的...

谢谢你的帮助。

编辑:

这是更大的滚动视图:

@implementation UIGridScrollView
- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    self.pagingEnabled;
    return self;
}
@end

现在,这个UIGridScroll查看,我添加作为一个子视图这样的观点:

@implementation UINoteView
{
IBOutlet UIScrollView *_innerScrollView; // this scrollview frame is in the size of the all UINoteView
}

- (void)awakeFromNib
{
    _innerScrollView.contentSize = CGSizeMake(_innerScrollView.frame.size.width, _innerScrollView.frame.size.height+50.0f);
}
@end

分页效果很好,内部滚动视图效果很好,但太多的时候,我寻呼的_innerScrollView更大的笔记看,我的手指“卡住”。

谢谢!

Answer 1:

@stanislaw,我刚刚试过你的iPhone设备上提出的解决方案。

我看到你的问题。

您的代码不会阻止垂直观点偶尔春联,但我认为这是不同步的手势识别不工作 - 评你为内欣赏到整个代码,并使用代码与以下修改外滚动视图:

@interface OuterHorizontalScrollView : UIScrollView ...
@property (weak) InnerVerticalScrollView *currentActiveView; // Current inner vertical scroll view displayed.
@end

@implementation OuterHorizontalScrollView
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
    if (self.currentActiveView.dragging == NO) {
        self.currentActiveView.scrollEnabled = NO; // The presence of this line does the job
    }
    return YES;
}

- (void)scrollViewDidEndDragging:(PlacesScrollView *)scrollView willDecelerate:(BOOL)decelerate {
    self.currentActiveView.scrollEnabled = YES; // This is very likely should be done for all subviews, not only a current.
}    
@end


Answer 2:

你可以继承UIScrollView和实施gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:允许滚动视图的内置panGestureRecognizer与另一个滚动视图的手势识别同时识别。

例:

//This is needed because the public UIScrollView headers
//don't declare the UIGestureRecognizerDelegate protocol:
@interface UIScrollView (GestureRecognition) <UIGestureRecognizerDelegate>
@end

@interface MyScrollView : UIScrollView

@end

@implementation MyScrollView

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
    if (gestureRecognizer == self.panGestureRecognizer) {
        return YES;
    } else if ([UIScrollView instancesRespondToSelector:@selector(gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:)]) {
        //Note: UIScrollView currently doesn't implement this method, but this may change...
        return [super gestureRecognizer:gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:otherGestureRecognizer];
    }
    return NO; //the default
}

@end

使用这个子类无论是水平,或所有垂直滚动视图应该足够了。

你实际上可能找到你喜欢的默认行为更好,你用这种方式尝试之后。 允许这两种观点同时滚动几乎总是导致意外垂直滚动,同时向左和向右滑动,可刺激(大多数人不这样做完全水平轻扫手势)。



Answer 3:

我有点糊涂大你的设置,但你可能想看看-[UIScrollView setDelaysContentTouches:] 。 你可以用它与嵌套的滚动视图处理时添加的优先位。



Answer 4:

一旦我遇到这种情况与我有以下工作各地做到了这一点。

从UIScrollView的子类均视图的&你会被罚款与此有关。 你的情况,我可以看到你的UINoteView不是从UIScrollView的子类,从滚动型继承它与从该类别中删除innerScrollView。



Answer 5:

下面是如何我都做到了:

在垂直滚动视图中使用shouldRecognizeSimultaneouslyWithGestureRecognizer(感谢@omz!)和自定义的滑动手势识别(见类似的问题

水平滚动的UIScrollView垂直平移手势 ),我有以下设置:

@interface UIScrollView (GestureRecognition) <UIGestureRecognizerDelegate>
@end

@interface OuterHorizontalScrollView : UIScrollView ...
@property (weak) InnerVerticalScrollView *currentView; // Current inner vertical scroll view displayed.
@end

@implementation OuterHorizontalScrollView
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
    if (self.currentActiveView.placeVerticalScrollView.dragging == NO) {
        self.currentActiveView.placeVerticalScrollView.scrollEnabled = NO;
        return YES;
    } else {
        return NO;
    }
}    
@end

@interface InnerVerticalScrollView : UIScrollView...
@property UISwipeGestureRecognizer *swipeGestureRecognizer;
@end

@implementation InnerVerticalScrollView
- (id)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
        ...
        self.swipeGestureRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleSwipeGesture:)];
        self.swipeGestureRecognizer.direction = UISwipeGestureRecognizerDirectionDown | UISwipeGestureRecognizerDirectionUp;
        [self addGestureRecognizer:self.swipeGestureRecognizer];
    }

    return self;
}

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
    if (gestureRecognizer == self.panGestureRecognizer && self.scrollEnabled == YES) {
        return YES;
    } else if (gestureRecognizer == self.swipeGestureRecognizer) {
        return YES;
    } else {
        self.scrollEnabled = NO;
    }

    return NO;
}

- (void)handleSwipeGesture:(UIGestureRecognizer *)sender {
    self.scrollEnabled = YES;
}

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {    
    return YES;
}

这个代码是有点哈克:它允许仅当它们的自定义滑动手势被识别(仅顶部或底部的方向),所有其他手势被传递到外周涡旋视图这反过来允许任何手势只有如果没有人的垂直滚动视图滚动的内周涡旋视图被拖动。

注意:这不是明显的滑动手势适用于缓慢或微小挥笔过,但它(又见评价报价问题上)。

我觉得它可以实现更容易,也许我会在后面重构它。

不管怎样,现在外滚动完美的作品 - 它水平滚动无内滚动视图中的任何偶然的垂直平移。

以后更新:正如我之前的预期,我的解决方案的确含有不必要的代码位:一看便知通过@burik,同时部分基于我的解决方案,它需要这些位出来。



Answer 6:

我想用速度来确定滚动方向是一个更好的办法:

- (BOOL)gestureRecognizerShouldBegin:(UIPanGestureRecognizer *)gestureRecognizer {
    CGPoint velocity = [gestureRecognizer velocityInView:gestureRecognizer.view];
    return fabs(velocity.y) > 3 * fabs(velocity.x);
}


文章来源: Horizontal UIScrollView having vertical UIScrollViews inside - how to prevent scrolling of inner scroll views when scrolling outer horizontal view?