【问题标题】:How to stop UITextView from scrolling when fingers are lifted (Swift 4)抬起手指时如何阻止 UITextView 滚动(Swift 4)
【发布时间】:2026-01-09 12:50:02
【问题描述】:

我有一个 textView,其内容可能超过视图的高度,所以我希望能够向下滚动,在我想要的时候停止,并在停止后返回时向上滚动。

问题

当滚动(用两根手指)时,会发生两件事:

  • 顶行滚动到上面的视图中
  • 当手指从屏幕上抬起时,视图会弹回顶部。

问题

  • 如何防止 textView 框架上方的数据滚动到其上方的视图中?
  • 当他们的手指离开屏幕时如何停止滚动?用户抬起手指时会调用哪些事件?
import UIKit

class ScrollableView: UIView, UITextViewDelegate {

    var displayData = UITextView()

    override func draw(_ rect: CGRect) {
        super.draw(rect)        
        displayData.delegate = self

        getContent()
        calculateFrameBounds()
        displayTallTable()
    }

    func getContent() {
    }

    func calculateFrameBounds() {
    }

    func displayTallTable() {
        displayData.frame = CGRect(x: x, y: y, width: w, height: h)        
        self.addSubview(displayData)
    }
}

【问题讨论】:

  • 为什么不将 UITextView 添加到 scrollView 中?有关更多信息,请查看 scrollView 的委托 UIScrollViewDelegate 中的回调。此外,您可以通过切换 scrollView.isScrollEnabled 来强制停止滚动
  • 这就是我开始的地方,但因为UITextView 已经是UIScrollView 的子类而将其删除。
  • 您仍然可以在您的 UITextView 上设置一个委托并观察对回调的响应
  • 是的,我现在已经让回调工作(见下文),但现在不知道如何在手指抬起时停止滚动。

标签: ios swift


【解决方案1】:

使用 touchesEnded 函数,每当触摸事件结束时都会调用此函数。

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
            // implement in this function, when fingers are lifted this function is called.
        }
        

【讨论】:

  • 我添加了这个,但它没有被调用。我也试过touchesCancelled,但它也没有被调用。
  • 也尝试添加super.touchesEnded(touches, with: event),但没有帮助。
  • 我刚刚发现这些确实被调用了,但只有超级视图,而不是 UITextView。
  • 我已将触摸功能(开始、结束、取消、移动)添加到 extension UITextView ,它们现在会响应。
  • 下一个问题是我在这些函数中做什么???调用 touchesEnded 时如何停止冻结视图?
【解决方案2】:

部分答案:

为了能够停止和恢复滚动,事实证明 UITextView (displayData) 的高度需要小于其内容。我需要做的就是将它的高度设置为包含它的 UIView 的高度。

UITextView (displayData) 位于 UIView 容器内。为了防止displayData 的文本滚动到相邻视图(UIView 容器上方和下方),我只需要像这样打开 UIView 容器上的 clipsToBounds:super.clipsToBounds = true(或选中 IB 中的框)。

不过,这只是部分解决方案。因为我在 UITextView (displayData) 和它的 UIView 容器的顶部和底部之间有间隙,所以数据仍然会从 UITextView 滚动到 UIView 的间隙中。

我尝试了以下所有方法,但均未成功:

displayData.clipsToBounds = true
displayData.contentInset = UIEdgeInsets.zero
displayData.layer.masksToBounds = true

我们将不胜感激任何有关这最后一部分的帮助!

【讨论】: