使用 scrollViewWillEndDragging 确保 UIScrollView 在定义的增量处停止

Posted

技术标签:

【中文标题】使用 scrollViewWillEndDragging 确保 UIScrollView 在定义的增量处停止【英文标题】:using scrollViewWillEndDragging to ensure UIScrollView stops at defined increments 【发布时间】:2015-07-23 19:08:23 【问题描述】:

我希望我的UIScrollView 在某些增量值处自然滑动到结尾,对应于水平滚动UIScrollView 的每 50 个宽度点为此,我自定义了 scrollViewWillEndDragging,就像这样(推荐,但是此处未在答案中详细描述Scrolling a horizontal UIScrollView in stepped increments?):

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


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

我细化滚动不会以 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];

【问题讨论】:

在你的委托方法中 - (void) scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset 在新的 '*targetContentOffset' 中替换 'contentOffset'目标偏移计算。 【参考方案1】:

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

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

    使您的滚动视图与您的其中一项具有相同的宽度(在您的情况下为 50.0 个单位)。 将 scrollView.clipsToBounds 设置为 false,以便滚动视图在其更小的范围之外绘制子视图。 将scrollView.pagingEnabled 设置为true,以便滚动视图随分页一起滚动。

此时,分页将起作用,但您将无法将滚动视图拖动到其边界之外。要完成这项工作,您需要将滚动视图嵌入到更大的视图中,以便将触摸事件转发给它。

    创建一个“触摸转发”类并将其添加到您的视图中。

这个类接受它接收到的所有触摸事件并将它们发送到它的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 个单元页面。

【讨论】:

以上是关于使用 scrollViewWillEndDragging 确保 UIScrollView 在定义的增量处停止的主要内容,如果未能解决你的问题,请参考以下文章

在使用加载数据流步骤的猪中,使用(使用 PigStorage)和不使用它有啥区别?

今目标使用教程 今目标任务使用篇

Qt静态编译时使用OpenSSL有三种方式(不使用,动态使用,静态使用,默认是动态使用)

MySQL db 在按日期排序时使用“使用位置;使用临时;使用文件排序”

使用“使用严格”作为“使用强”的备份

Kettle java脚本组件的使用说明(简单使用升级使用)