swift - 如何为 UILabel 文本大小(和颜色)设置动画

标签 swift animation uikit uilabel

关于动画化 UILabel 的文本大小,Stack Overflow 周围似乎有很多“快速修复”的答案,这些答案是由不太关心了解内容的用户发布的发生在引擎盖下。

对于以设计为导向的开发人员来说,看到这一点令人沮丧。大多数答案建议在 UILabel 上指定一个 transform,按 x 缩放,如下所示:

let label = UILabel()
label.text = "yourText"
label.sizeToFit()
label.layer.anchorPoint = CGPoint(x: 0, y: 0)
label.layer.position = CGPoint(x: 0, y: 0)
UIView.animate(withDuration: duration) {
    label.transform = CGAffineTransform(scaleX: 4.0, y: 4.0)
}

产生以下动画:

Alt Text

但是,它看起来很模糊 — 并且标签的跟踪值不适应比例。 那么,为 UILabel 设置文本大小动画的最佳方式是什么?

最佳答案

正如我提到的,将 CGAffineTransform 应用于 UILabel 以对其进行缩放对于面向设计的开发人员来说是令人沮丧的,原因有两个。

  1. 转换 不考虑跟踪和字体变体。 San Francisco(Apple 的系统字体)根据文本大小使用其字体的两种不同 变体。

iOS automatically applies the most appropriate variant based on the point size and the user's accessibility settings. Adjust tracking—the spacing between letters—appropriately.

SF Pro Text 应用于 19 磅或更小的文本,而 SF Pro Display 应用于 20 磅或更大的文本。对于每个点大小,每个变体都有不同的“跟踪”值——字母之间的间距(请参阅:Font Usage and Tracking 下的许多跟踪值)。

不幸的是,CGAffineTransform 没有设置新的 pointSize,否则会强制重绘 View 。应用转换只是缩放 UILabel 的光栅化位图,这意味着字体和跟踪值不是自适应的。因此,如果我们将标签从 10pt 缩放到 20pt,生成的 20pt 处的 UILabel 仍将使用具有 12pt 跟踪的 SF Pro Text,而不是具有 19pt 跟踪的 SF Pro Display。您可以在下面看到红色标签已转换,因此不会调整其字体。

  1. 转换 View 或图层会导致模糊。如前所述,Core Graphics 不会重新渲染 View ,而是转换 View 的 2D 像素图。下面的红色标签显然是模糊的。

解决方案

我们最好的选择是使用 CATextLayer 而不是 UILabel,Apple 是这样说的:

A layer that provides simple text layout and rendering of plain or attributed strings.

CATextLayer 文档列表 var string: Any?, var font: CFTypeRef?, var fontSize: CGFloatvar foregroundColor: CGColor? 等属性,大多数时候我们只需要这些。完美!

我们需要做的就是添加一个CAPropertyAnimation——比如CABasicAnimation——到CATextLayer来动画它的属性,像这样:

// Create the CATextLayer
let textLayer = CATextLayer()
textLayer.string = "yourText"
textLayer.font = UIFont.systemFont(ofSize: startFontSize)
textLayer.fontSize = startFontSize
textLayer.foregroundColor = UIColor.black.cgColor
textLayer.contentsScale = UIScreen.main.scale
textLayer.frame = view.bounds
view.layer.addSublayer(textLayer)

// Animation
let duration: TimeInterval = 10
textLayer.fontSize = endFontSize
let fontSizeAnimation = CABasicAnimation(keyPath: "fontSize")
fontSizeAnimation.fromValue = startFontSize
fontSizeAnimation.toValue = endFontSize
fontSizeAnimation.duration = duration
textLayer.add(fontSizeAnimation, forKey: nil)

瞧!下面的黑色文本是我们适当缩放的 CATextLayer。锐利且具有正确的字体变体。

Alt Text

h/t to Yinan 索取密码:https://stackoverflow.com/a/42047777/4848310 . Yinan 还讨论了如何将 CATextLayer 与基于自动布局约束的动画一起使用。


奖励!这也适用于动画文本颜色!只需使用 foregroundColor 属性即可。

关于swift - 如何为 UILabel 文本大小(和颜色)设置动画,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46536530/

相关文章:

ios - 如何使用自动布局约束在表格单元格中安装 2 个可变大小的标签,该表格单元格的高度是使用估计的 HeightForRowAtIndexPath 估计的

swift - 无法获取 firebase 子节点

Android:在内部充气 RecyclerView 时,如何防止 Fragment 事务的延迟或动画跳过?

ios - 如何减少 UITabBarItem 图像和文本之间的垂直填充?

json - 设置或覆盖通用编码对象的属性

ios - 不能为类型值添加下标

javascript - 任何拉伸(stretch)背景图像的方法

ios - 在容器 View 中交换 subview

ios - 将相同的 UITableView 添加到不同的 ViewControllers

ios - 在带有IOS 6的iPad上展示aN操作表时崩溃