You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Xcode 9(Swift)中实现文本自动右滑并禁用手动滚动

实现类似Spotify的文本自动滚动效果(Xcode 9 + UITextView)

我之前刚好做过类似的需求,用UITextView完全能实现你想要的效果,下面是具体的实现步骤,一步步来:

1. 基础配置UITextView

首先得把TextView的手动滚动给禁用掉,同时确保内容能正常超出边界:

// 假设你的TextView实例名为scrollableTextView
scrollableTextView.isScrollEnabled = false
scrollableTextView.isUserInteractionEnabled = false // 可选,若不想让用户选中/编辑文本
scrollableTextView.textContainerInset = .zero
scrollableTextView.textContainer.lineFragmentPadding = 0

这样用户就没法手动拖动滚动,只能由我们控制自动滚动逻辑。

2. 判断是否需要启动滚动

只有当文本内容的宽度超过TextView的可视宽度时,才需要触发滚动动画,避免无意义的执行:

private func shouldStartScrolling() -> Bool {
    let textTotalWidth = scrollableTextView.sizeThatFits(
        CGSize(width: CGFloat.greatestFiniteMagnitude, height: scrollableTextView.bounds.height)
    ).width
    return textTotalWidth > scrollableTextView.bounds.width
}

3. 实现自动滚动+复位的循环动画

用UIView的平滑动画实现滚动效果,滚动到末端后延迟一段时间再复位,接着重复整个流程:

private func startAutoScrollLoop() {
    guard shouldStartScrolling() else { return }
    
    let maxOffsetX = scrollableTextView.contentSize.width - scrollableTextView.bounds.width
    // 根据文本长度动态计算滚动时长,这里按每100pt用1秒的比例,你可以按需调整
    let scrollDuration = maxOffsetX / 100.0
    
    // 滚动到文本最右侧
    UIView.animate(withDuration: scrollDuration, delay: 0, options: .curveLinear, animations: {
        self.scrollableTextView.contentOffset = CGPoint(x: maxOffsetX, y: 0)
    }) { [weak self] _ in
        guard let self = self else { return }
        // 停留2秒后复位(可自定义停留时长)
        DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
            UIView.animate(withDuration: 0.3, animations: {
                self.scrollableTextView.contentOffset = .zero
            }) { [weak self] _ in
                // 复位后等待1秒,再次启动滚动循环(可自定义间隔)
                DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
                    self?.startAutoScrollLoop()
                }
            }
        }
    }
}

4. 动画的触发与停止

  • 在视图加载完成、文本内容更新后,调用startAutoScrollLoop()启动动画
  • 若需要停止动画(比如文本变短、页面切换),可以执行:
scrollableTextView.layer.removeAllAnimations()
scrollableTextView.contentOffset = .zero

额外注意点

  • 如果TextView的frame会动态变化(比如屏幕旋转),记得在viewDidLayoutSubviews()里重新判断并重启滚动逻辑
  • 动画时长、停留间隔都可以根据你的UI风格调整,让滚动更贴合产品体验
  • 上述代码针对单行文本优化,若要支持多行,需要额外调整高度相关的判断逻辑

内容的提问来源于stack exchange,提问作者probot

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 09:30:37