ToB企服应用市场:ToB评测及商务社交产业平台

标题: iOS 打字机结果与光标追随 [打印本页]

作者: 干翻全岛蛙蛙    时间: 2024-11-20 13:22
标题: iOS 打字机结果与光标追随
媒介

在最近的开发中需要接入一个 AI 模块,UI 上有类似于 chatGPT App 的一些交互体验设计。后端的接口也与 OpenAI 一样多次返回。所以需要写一个打字机的结果,并且有一个移动光标不停跟随文字的显示。简单写了个 demo 模拟一下后端返回,实现这个小需求。
项目地址:TypeFlowView on GitHub

思路

实现主要包罗以下几点:
主要代码

1. 随机拼文本,模拟后端不停返回

  1.     //appends a random portion of the remaining text and updates the text view and cursor accordingly
  2.     private func appendText() {
  3.         guard let curNews = curNews, curIdx < curNews.count else {
  4.             finishAnimation()
  5.             return
  6.         }
  7.         let remainingLength = curNews.count - curIdx
  8.         let maxReadLength = min(5, remainingLength)
  9.         let read = Int.random(in: 1...maxReadLength)
  10.         let startIndex = curNews.index(curNews.startIndex, offsetBy: curIdx)
  11.         let endIndex = curNews.index(startIndex, offsetBy: read)
  12.         let substring = String(curNews[startIndex..<endIndex])
  13.         textView.text += substring
  14.         updateTextViewHeight()
  15.         updateCursorPosition()
  16.         curIdx += read
  17.     }
复制代码
2. 使用 CADisplayLink

  1.     private func setupDisplayLink() {
  2.         displayLink = CADisplayLink(target: self, selector: #selector(update))
  3.         displayLink?.preferredFramesPerSecond = Int(1/updateInterval)
  4.         displayLink?.add(to: .main, forMode: .common)
  5.     }
  6.     @objc private func update(displayLink: CADisplayLink) {
  7.         guard lastUpdateTime == 0 || displayLink.timestamp - lastUpdateTime >= updateInterval else {
  8.             return
  9.         }
  10.         lastUpdateTime = displayLink.timestamp
  11.         appendText()
  12.     }
复制代码
使用 CADisplayLink 而不是 Timer 来控制文本的显示。CADisplayLink 与屏幕刷新率同步,可以提供更流通的动画结果。
3. 更新光标位置

  1.     private func updateCursorPosition() {
  2.         guard let selectedRange = textView.selectedTextRange else { return }
  3.         let cursorRect = textView.caretRect(for: selectedRange.end)
  4.         
  5.          UIView.animate(withDuration: 0.1, animations: {
  6.              self.cursorView.alpha = 0.2
  7.              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)
  8.          }) { _ in
  9.              UIView.animate(withDuration: 0.05) {
  10.                  self.cursorView.alpha = 1
  11.              }
  12.          }
  13.     }
复制代码
尾声

还可以做的:

顺手写的 demo,考虑的可能不太周全,性能上也没有寻求多好。完整代码 TypeFlowView on GitHub

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4