首先,在创建项目并初始化界面时添加一个UILabel到视图控制器的主要视图里:
swift
import UIKit
class MarqueeLabelViewController: UIViewController {
var label: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// 设置label的基本样式及内容
label = UILabel(frame: CGRect(x: 0, y: view.bounds.height / 2 - 30, width: view.frame.width, height: 60))
label.textColor = .white
label.textAlignment = .center
label.text = "这是一个模拟跑马灯效果的消息"
// 添加至主窗口以便显示
self.view.addSubview(label)
}
}
接下来是关键步骤:运用NSTimer周期性地改变UILabel的位置以达到移动的效果。为了确保文本无缝循环流动,我们需要对原字符串复制后拼接形成新的较长字符串,并随着每次计时期满调整LABEL的内容以及起始位置。
以下是具体实现实现逻辑的核心部分:
swift
var timer : Timer?
let animationDuration: TimeInterval = 5.0 // 动画时间间隔自行设定
func startMarqueeAnimation() {
let textToScroll = (1...2).map { _ in label.text! }.joined(separator:" ")
if !timer.isValid {
timer = Timer.scheduledTimer(withTimeInterval:animationDuration/CGRectGetWidth(label.frame), repeats: true) { [weak self] _ in
guard let strongSelf = self else { return }
UIView.animate(withDuration: animationDuration, animations: {
if let currentText = strongSelf.label.text,
let rangeOfString = currentText.range(of:textToScroll),
let startIndex = String(textToScroll.prefix(rangeOfString.lowerBound)).firstIndex(of: "")?.advanced(by:-1) ?? 0 {
let newString = String(currentText[..<startIndex]) + String(textToScroll.dropFirst())
strongSelf.labelX -= CGFloat(UIFont.systemFontSize)
strongSelf.labelX = max(strongSelf.labelX, -(strongSelf.labelX + CGRectGetWidth(strongSelf.label.frame)))
strongSelf.label.text = newString
}
}, completion:nil)
}
}
}
// 调整x坐标初始值防止跳动
private(set) lazy var xCoordinateOffset: CGFloat = -(CGRectGetWidth(self.label.frame))
@objc private dynamic var layoutX: CGFloat = xCoordinateOffset {
didSet {
label.center.x = UIScreen.main.bounds.midX + layoutX
}
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
startMarqueeAnimation()
}
deinit {
timer?.invalidate()
}
上述代码的工作原理如下:
- 我们先用`startMarqueeAnimation()`函数启动了一个基于NSTimer的定时任务,该任务会在指定的时间间隔内重复执行。
- 在每一次计时回调中,我们计算当前需要移除的第一个字符索引并通过Swift集合操作生成新串,使原始消息向左平滑过渡。
- 同步更新 `layoutX`(即UILabel的实际水平偏移量),并在UIView的animate方法块内部设置其text属性与frame变化,使得动画得以连续而自然地展现出来。
最后,在view即将出现的时候调用开始跑马灯的方法,并在对象销毁前取消定时器以防内存泄漏。
这样就实现了基础版的跑马灯效果。此方案可根据实际应用场景灵活扩展优化,如支持自定义速度、方向等特性。总的来说,借助于iOS SDK中的NSTimer与UIKit框架下的UILabel控件相互配合可以轻松构建视觉吸引力十足的信息展示方式——跑马灯特效。