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

时间:2017-10-03 02:52:39

标签: swift animation uikit uilabel

关于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)
}

导致以下动画:

Alt Text

但是,它看起来很模糊 - 标签的跟踪值不适应规模。 那么,为UILabel的文字大小制作动画的最佳方式是什么?

3 个答案:

答案 0 :(得分:5)

正如我所提到的,将CGAffineTransform应用于UILabel以扩展它对于面向设计的开发人员来说是令人沮丧的,原因有两个。

  1. transform并未考虑跟踪和字体变体。旧金山(Apple的系统字体)根据文本大小使用其字体的两个不同的变体。
  2.   

    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。您可以在下面看到红色标签已被转换,因此不会调整其字体。

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

      我们最好的选择是使用CATextLayer代替UILabel,Apple称之为:{/ p>

        

      提供简单文本布局和呈现普通或属性字符串的图层。

      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到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!这也为您节省了维护代码的时间和麻烦。