【问题标题】:How to Cancel Scrolling in UIScrollView如何在 UIScrollView 中取消滚动
【发布时间】:2023-04-04 21:10:02
【问题描述】:

我使用 UIScrollView 在 iPhone 上制作大尺寸(大于 320 像素)的 UI。

我创建了一个 UIScrollView 实例并在其上添加了一些子视图。 问题是我只想在用户触摸子视图之外时启用滚动, 当用户触摸其中一个子视图时停止滚动。

我阅读了文档并尝试查找示例,但找不到好的提示。 如果您有任何想法,请帮助我。

【问题讨论】:

  • @Chris Hanson:为什么要从标签中删除 iPhone 和 UIScrollView?这些是正确的标签 - 可以添加 cocoa-touch,但不应在这里单独存在。
  • 我没有删除或编辑这些标签 :(
  • 因为在我进行编辑时,用类名和冗余信息污染标签空间并不是一个好主意。它仍然不是,我只是放弃了修复那个废话。

标签: iphone cocoa-touch uiscrollview


【解决方案1】:

UIScrollView 有一个 scrollEnabled 属性,允许您以编程方式禁用滚动。它还有一个委托 (UIScrollViewDelegate),允许您查看诸如滚动开始/结束之类的事件。似乎您应该能够以某种方式将这些选项组合起来。

【讨论】:

  • 感谢您的回复。我现在就试试你的解决方案。
  • 不错的答案,含糊不清,但足以开始。 +1
【解决方案2】:

你真正感兴趣的属性——我现在正在测试它,因为我遇到了同样的问题——是canCancelContentTouches

如果此属性的值为 NO, 滚动视图不滚动 无论手指移动一次 内容视图开始跟踪。

如果这不能为您提供所需的结果,请将 UIScrollView 子类化并覆盖 touchesShouldBegin:withEvent:inContentView 方法,这是公认的答案所建议的。

【讨论】:

    【解决方案3】:

    如果您想检测 UIScrollView 的任何子视图内的触摸,则必须将 UIScrollView 子类化并覆盖专门为此目的创建的 touchesShouldBegintouchesShouldCancelInContentView 方法。

    除此之外,您无法识别子视图中的触摸,因为 UIScrollView 倾向于自行处理所有触摸并且不会将它们传递给其子视图。

    一切顺利。

    【讨论】:

    • 感谢您的回答。我试图覆盖 touchesShouldBegin / touchesShouldCancel... 方法,但从未调用过这些方法。也许我的编码有问题,但我可以通过覆盖 touchesBegin/touchesMoved/touchedEnded 方法来停止滚动。谢谢!
    • 您是在 UIScrollView 的子类中执行此操作吗?只有在那时才会调用这些方法。因此,您的 UIViewController 不应使用 UIView 作为其视图,而应使用 UIScrollView 的子类作为视图
    • 是的,我在 UIScrollView 的子类中尝试过这个。我在我的实现中遇到了一些问题(只覆盖了 touchesBegan...),所以我一直在尝试找出为什么 touchesShouldBegin 方法从未被调用过的原因。
    • 我遇到了同样的问题。对我来说,这是由于底层子视图(UIImageView)没有将 userInteractionEnabled 设置为 YES。
    • 这个答案是错误的,不应该是公认的答案。您根本不必继承 UIScrollView。 UIScrollView 中有一个错误会破坏 UIViews - 如果您修复 UIView,所有触摸都可以正常工作(它们会通过 UIViewController)并且滚动视图继续按预期工作。秘诀是在苹果不小心删除的时候在UIView子类中正确设置nextResponder
    【解决方案4】:

    最简单的方法是将滚动视图的delaysContentTouches 设置为NO。这样就设置了默认行为,这样任何 UIControl 都会立即将触摸传递给控件,​​而其他所有内容都会滚动。

    【讨论】:

    • 如果设置为 NO,则行为与 OP 想要的相反。如果将其设置为 YES,那也好不到哪里去 :)
    【解决方案5】:

    您还可以子类化 UIScrollViewController 并覆盖 touchesBegan、touchesMoved 和 touchesEnded 方法。如果您的实现从不调用超类实现,则它不会滚动。

    【讨论】:

    • 感谢您的回答。我试过你的建议,它奏效了!!
    【解决方案6】:

    我的问题是有一个用户可以绘制的视图,但滚动视图劫持了触摸和滚动而不是绘制。这是我的工作解决方案:

    在我的绘图视图中,我有:

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    
        // Disable scroll on touch begin
        setContainerScrollingEnabled(false)
        super.touchesBegan(touches, with: event)
    }
    
    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
    
        // Reenable scroll on touch end
        setContainerScrollingEnabled(true)
        super.touchesEnded(touches, with: event)
    }
    
    private func setContainerScrollingEnabled(_ enabled: Bool) {
    
        // loop up superviews to find the scrollview
        func scrollingSuperview(of view: UIView) -> UIScrollView? {
            guard let superview = view.superview else { return nil }
            if let scrolling = view.superview as? UIScrollView { return scrolling }
            return scrollingSuperview(of: superview)
        }
    
        // and switch on/off scrolling
        let scrollView = scrollingSuperview(of: self)
        scrollView?.isScrollEnabled = enabled
    }
    

    在包含滚动视图的视图控制器中:

    // Not sure what exactly this does, but I think it allows the drawing view to have precedence. This was the missing piece of the puzzle.
    scrollView.delaysContentTouches = false
    

    【讨论】:

    • 这对我有用。顺便说一句,您可能也希望在 touchesCancelled 上启用滚动!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多