展开UIScrollView交互区域并区分滑动和点击

时间:2016-08-11 22:13:49

标签: ios objective-c uiscrollview scroll-paging

我正在使用UIScroll View创建一个具有分页功能的类似库的UI。基本上是这样的:

enter image description here

由于我需要分页,所以我将scrollview的宽度设置为单页的宽度,在我的例子中,是粉红色矩形的宽度。

但我还想要两件事:

  1. 点击黄色或蓝色区域会将相应的矩形带到中心。
  2. 可以在黄色或蓝色区域(滚动视图外)滚动/滑动,这意味着屏幕的整个宽度都可以滚动。
  3. 我关注了this thread并添加了- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event通过这样做,我只能实现我的第二个目标。当我设置选择器或委托处理攻击黄色和蓝色的反应时,它不起作用。有什么想法吗?

1 个答案:

答案 0 :(得分:1)

That answer you referenced是我最喜欢的一个。它没有考虑你的第一个要求,但我认为它只需添加一个轻敲手势识别器就可以非常巧妙地处理它。

在“ClipView”上创建它:

UITapGestureRecognizer *tapGR = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tap:)];
[self.myClipView addGestureRecognizer:tapGR];
// myClipView is the view that contains the paging scroll view

- (void)tap: (UITapGestureRecognizer *)gr {
    // there are a few challenges here:
    // 1) get the tap location in the correct coordinate system
    // 2) convert that to which "page" was tapped
    // 3) scroll to that page
}
由于手势识别器回答locationInView:

挑战1)很容易

CGPoint location = [gr locationInView:self.scrollView]; 

对于挑战2)我们需要确定点击滚动视图中的哪个页面。这可以通过给定页面宽度的非常简单的算术来完成。

// assuming you have something like this
#define kPAGE_WIDTH    // some float

// page is just how many page-width's are represented by location.y
NSInteger page = floor(location.y/kPAGE_WIDTH);

现在,挑战3)现在很容易,因为我们可以直接将页面更改为滚动位置......

CGFloat y = page * kPAGE_WIDTH;
[self.scrollView setContentOffset:CGPointMake(y, 0.0f) animated:YES];

或者,在一大块代码中......

- (void)tap: (UITapGestureRecognizer *)gr {
    CGPoint location = [gr locationInView:self.scrollView]; 
    NSInteger page = floor(location.y/kPAGE_WIDTH);
    CGFloat y = page * kPAGE_WIDTH;
    [self.scrollView setContentOffset:CGPointMake(y, 0.0f) animated:YES];
}

修改

您可能还想从手势识别器中排除“当前页面”区域。这只是通过在tap方法中对测试进行限定来完成的。

唯一的技巧是将抽头位置设置在与滚动视图框架相同的坐标系中,即剪辑视图......

CGPoint locationInClipper = [gr locationInView:gr.view]; 

SDK提供了一种很好的测试方法......

BOOL inScrollView = [self.scrollView pointInside:locationInClipper withEvent:nil];

因此...

- (void)tap: (UITapGestureRecognizer *)gr {
    CGPoint locationInClipper = [gr locationInView:gr.view]; 
    BOOL inScrollView = [self.scrollView pointInside:locationInClipper withEvent:nil];

    if (!inScrollView) {
        CGPoint location = [gr locationInView:self.scrollView]; 
        NSInteger page = floor(location.y/kPAGE_WIDTH);
        CGFloat y = page * kPAGE_WIDTH;
        [self.scrollView setContentOffset:CGPointMake(y, 0.0f) animated:YES];
    }
}