使用scrollviewwillenddrag来确保UIScrollView停止在定义的增量



我希望我的UIScrollView能够自然地滑动到某些增量值的结尾,对应于水平滚动UIScrollView的每50点宽度。为此,我自定义了scrollviewwillenddrag,就像这样(按照建议,但没有详细描述在这里的答案中滚动水平UIScrollView以步进增量?):

- (void) scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset{
    if(fmodf(targetContentOffset->x, 50.0)){
        int roundingNumber1 = 50;
        CGFloat newOffset = roundingNumber1 * floor(((scrollView.contentOffset.x)/roundingNumber1)+0.5);
        targetContentOffset->x = newOffset;
    }
}

然而,我不确定这实际上是以特定的增量停止视图,并且我还注意到效果是不对称的。虽然我的滚动运动/速度/等是相同的,向右滚动远不如向左滚动流畅。向右滚动停止得更快、更突然。这里有一个视频。为什么这种行为是不对称的,我该如何改变它?

我认为滚动不会以50的增量停止的原因是,我在滚动视图下面也有一个UILabel,由其他委托函数更新以显示偏移量。滚动完成后,它显示的值很少接近50。这是因为滚动没有增加到50的值,还是因为我没有在正确的时间更新?

谢谢你的建议。

- (void) scrollViewDidScroll:(UIScrollView *)scrollView{
    if(abs(self.lastOffset - scrollView.contentOffset.x) > 49){
        CGFloat newNumber = scrollView.contentOffset.x;
        self.numberProperty.text = [NSString stringWithFormat:@"%.00f", scrollView.contentOffset.x];
        self.lastOffset = scrollView.contentOffset.x;
        [self.view setNeedsDisplay];
    }
}
- (void) scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView{
            self.numberProperty.text = [NSString stringWithFormat:@"%.00f", scrollView.contentOffset.x];
}

您可以将滚动视图上的pagingEnabled设置为true,而不是实现这些委托方法,以免费获得此行为。当分页被启用时,当你结束拖动时,滚动视图会自动抓取到最近的"页面",其中页面宽度等于滚动视图的宽度。

根据您的视频,看起来滚动视图中的项目比滚动视图本身的宽度小。要使用分页,您必须执行以下操作:

  1. 让你的滚动视图具有与你的一个项目相同的宽度(在你的情况下为50.0单位)。
  2. scrollView.clipsToBounds设置为false,以便滚动视图在其较小的边界之外绘制子视图。
  3. 设置scrollView.pagingEnabled为true,以便滚动视图滚动分页。

此时,分页将工作,但您将无法将滚动视图拖出其边界。要做到这一点,你需要将滚动视图嵌入到一个更大的视图中,该视图将触摸事件转发给它。

  • 创建一个"touch forwarding"类,并将其添加到视图中。

    这个类接受它接收到的所有触摸事件,并将它们发送给它的targetView属性。DJK是我为类名随机编的前缀。

    @interface DJKTouchForwardingView : UIView
    /** The view to which touch events should be forwarded. */
    @property (weak, nonatomic) UIView *targetView;
    @end
    @implementation DJKTouchForwardingView
    - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
    {
        UIView *child = nil;
        if ((child = [super hitTest:point withEvent:event]) == self) {
            return self.targetView;
        }
        return child;
    }
    @end
    
  • 使滚动视图成为触摸转发视图的子视图,并将其分配给targetView属性。
  • 你的滚动视图现在可以在触摸转发视图的范围内滚动,并将捕捉到50个单位页。

    最新更新