关于UILabel
的文本大小的动画,似乎有很多“快速修复”的答案浮现在Stack Overflow上,由那些不太了解在下面发生了什么的用户发布。引擎盖。
对于面向设计的开发人员来说,这令人沮丧。大多数答案建议在transform
上指定UILabel
,按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)
}
导致以下动画:
但是,它看起来很模糊 - 标签的跟踪值不适应规模。 那么,为UILabel
的文字大小制作动画的最佳方式是什么?
答案 0 :(得分:5)
正如我所提到的,将CGAffineTransform
应用于UILabel
以扩展它对于面向设计的开发人员来说是令人沮丧的,原因有两个。
transform
并未考虑跟踪和字体变体。旧金山(Apple的系统字体)根据文本大小使用其字体的两个不同的变体。 iOS会根据磅值和用户的辅助功能设置自动应用最合适的变体。适当调整跟踪 - 字母之间的间距。
SF Pro文本应用于19磅或更小的文本,而SF Pro Display应用于20磅或更大的文本。每个变体都有不同的跟踪"值 - 字母之间的间距 - 适用于每个磅值(请参阅:Font Usage and Tracking下的许多跟踪值)。
不幸的是,CGAffineTransform
没有设置新的pointSize
,否则会强制重绘视图。应用变换只会缩放UILabel
的光栅化位图,这意味着字体和跟踪值不具有自适应性。因此,如果我们将标签从10pt缩放到20pt到20pt,那么我们在20pt时得到的UILabel
仍然会使用带有12pt跟踪的SF Pro Text,而不是使用19pt跟踪的SF Pro Display。您可以在下面看到红色标签已被转换,因此不会调整其字体。
解决方案
我们最好的选择是使用CATextLayer
代替UILabel
,Apple称之为:{/ p>
提供简单文本布局和呈现普通或属性字符串的图层。
CATextLayer
个文档列表var string: Any?
,var font: CFTypeRef?
,var fontSize: CGFloat
,var 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
。夏普和正确的字体变体。
h / t到Yinan的代码:https://stackoverflow.com/a/42047777/4848310。 Yinan还讨论了如何将CATextLayer
与基于自动布局约束的动画结合使用。
奖金!这也适用于动画文字颜色!只需使用foregroundColor
属性。
答案 1 :(得分:0)
对于那些致力于使用Singleton
而不是UILabel
的人,我发现通过创建一个大字体大小的标签,可以将其缩小到0.25或者类似,然后将其缩放回1,如下所示:
CATextLayer
答案 2 :(得分:0)
尝试使用像这样的“Value Animator”。
https://github.com/brownsoo/ValueAnimator
用法:
import ValueAnimator
let animation = ValueAnimator.animate(
props: ["fontSizeChange"],
from: [10],
to: [100],
duration: 1,
easing: EaseSine.easeInOut(),
onChanged: { prop, animatedValue in
// Perform your animation
let value = CGFloat(animatedValue.value)
self.label.font = UIFont.systemFont(ofSize: value)
})
animation.resume()
注意:
值动画师只是在具有持续时间的 2 个值之间进行动画处理。这不仅可以用于更改字体大小。您可以将其用于旋转、大小更改、颜色更改、alpha 等。
这里的另一个好处是使用了超类本身。或者简单地说,在这个例子中,我们只是在动画UILabel
!这也为您节省了维护代码的时间和麻烦。