媒介
在最近的开发中需要接入一个 AI 模块,UI 上有类似于 chatGPT App 的一些交互体验设计。后端的接口也与 OpenAI 一样多次返回。所以需要写一个打字机的结果,并且有一个移动光标不停跟随文字的显示。简单写了个 demo 模拟一下后端返回,实现这个小需求。
项目地址:TypeFlowView on GitHub
思路
实现主要包罗以下几点:
- 定时器:为了实现文字的逐个显示,我们需要一个定时器来控制显示的节奏。
- 光标:我们将创建一个自界说视图来模拟光标,并使其位置随文本输入而更新。
- 动画:为了使结果更加生动,为光标添加一些简单的动画结果。
主要代码
1. 随机拼文本,模拟后端不停返回
- //appends a random portion of the remaining text and updates the text view and cursor accordingly
- private func appendText() {
- guard let curNews = curNews, curIdx < curNews.count else {
- finishAnimation()
- return
- }
- let remainingLength = curNews.count - curIdx
- let maxReadLength = min(5, remainingLength)
- let read = Int.random(in: 1...maxReadLength)
- let startIndex = curNews.index(curNews.startIndex, offsetBy: curIdx)
- let endIndex = curNews.index(startIndex, offsetBy: read)
- let substring = String(curNews[startIndex..<endIndex])
- textView.text += substring
- updateTextViewHeight()
- updateCursorPosition()
- curIdx += read
- }
复制代码 2. 使用 CADisplayLink
- private func setupDisplayLink() {
- displayLink = CADisplayLink(target: self, selector: #selector(update))
- displayLink?.preferredFramesPerSecond = Int(1/updateInterval)
- displayLink?.add(to: .main, forMode: .common)
- }
- @objc private func update(displayLink: CADisplayLink) {
- guard lastUpdateTime == 0 || displayLink.timestamp - lastUpdateTime >= updateInterval else {
- return
- }
- lastUpdateTime = displayLink.timestamp
- appendText()
- }
复制代码 使用 CADisplayLink 而不是 Timer 来控制文本的显示。CADisplayLink 与屏幕刷新率同步,可以提供更流通的动画结果。
3. 更新光标位置
- private func updateCursorPosition() {
- guard let selectedRange = textView.selectedTextRange else { return }
- let cursorRect = textView.caretRect(for: selectedRange.end)
-
- UIView.animate(withDuration: 0.1, animations: {
- self.cursorView.alpha = 0.2
- self.cursorView.frame = CGRect(x: Int(cursorRect.origin.x + self.textView.frame.origin.x), y: Int(cursorRect.origin.y + self.textView.frame.origin.y) + 4, width: 15, height: 15)
- }) { _ in
- UIView.animate(withDuration: 0.05) {
- self.cursorView.alpha = 1
- }
- }
- }
复制代码 尾声
还可以做的:
- 添加打字声音结果
- 支持富文本,允许差异样式的文字
- 优化内存使用,特别是对于非常长的文本
顺手写的 demo,考虑的可能不太周全,性能上也没有寻求多好。完整代码 TypeFlowView on GitHub
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |