【问题标题】:UILabel text change animation flickers when one text is longer than other当一个文本比另一个文本长时,UILabel 文本更改动画会闪烁
【发布时间】:2021-11-16 05:42:39
【问题描述】:

我正在使用理想的解决方案来为我的 UILabel 的文本更改设置动画。类似于这个答案https://stackoverflow.com/a/33705634/8704900
问题是当文本长度不同时,动画不再流畅并且文本在动画之前闪烁。
视频:https://drive.google.com/file/d/1I89NnzjQp7TbemO-dmcbKzYUr7pM7mGk/view?usp=sharing

我的代码如下所示:

@IBOutlet weak var label: UILabel!

var titleLabelAnimation: CATransition = {
        let animation = CATransition()
        animation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.default)
        animation.type = .push
        animation.subtype = .fromTop
        animation.duration = 0.5
        return animation
    }()

    @IBAction func didTap() {
        self.label.layer.add(self.titleLabelAnimation, forKey: nil)
        self.label.text = "Can you see a flicker?"
        self.label.sizeToFit()
    }
    
    @IBAction func didTapRev() {
        self.label.layer.add(self.titleLabelAnimation, forKey: nil)
        self.label.text = "Hello this is animation !!!"
        self.label.sizeToFit()
    }

我尝试了 layoutIfNeeded()、sizeToFit()、在动画之前更改文本以及其他几种解决方法。似乎没有任何效果!

【问题讨论】:

  • 我已经尝试过您的代码,如果我在前一个成功完成之前触发了新动画,则只能看到闪烁。这是您使用的系统所期望的。您忘记分享的代码是否还有其他内容? (我创建了一个新项目,添加了一个限制在屏幕中间的标签,在标签下方添加了 2 个按钮并复制并连接了您在此处发布的代码)。
  • 谢谢。就是这段代码:/我一定要留出时间让上一个动画完成。但是,当文本长度发生变化时,该问题是可重现的。问题也是间歇性的。但大多数时候很明显,如果你看到我附上的视频!您使用的是哪个版本的 Xcode 和 iOS 版本?

标签: ios swift animation uilabel catransition


【解决方案1】:

不确定您的示例中到底发生了什么,因为我无法生成此结果。但是动画在很多情况下是很痛苦的,而且很多东西可能会产生跳跃的视图。

通过对动画进行更多控制,您可能会更幸运地发现问题或解决问题。对于您的特定情况,使用快照制作动画可能已经足够了。查看以下内容:

@IBOutlet weak var label: UILabel!

private func animateAsCustom(applyChanges: @escaping (() -> Void)) {
    guard let viewToMove = label else { return }
    guard let panel = viewToMove.superview else { return }
    guard let snapshotView = viewToMove.snapshotView(afterScreenUpdates: true) else { return }
    
    applyChanges()
    
    UIView.performWithoutAnimation {
        panel.addSubview(snapshotView)
        snapshotView.center = viewToMove.center
        viewToMove.transform = CGAffineTransform(translationX: 0.0, y: 50.0) // TODO: compute values for translation
        viewToMove.alpha = 0.0
    }
    UIView.animate(withDuration: 0.5, delay: 0.0, options: .curveEaseIn) {
        viewToMove.transform = .identity
        snapshotView.transform = CGAffineTransform(translationX: 0.0, y: -50.0)
        snapshotView.alpha = 0.0
        viewToMove.alpha = 1.0
    } completion: { _ in
        snapshotView.removeFromSuperview()
    }
}

@IBAction func didTap() {
    animateAsCustom {
        self.label.numberOfLines = 1
        self.label.text = "Can you see a flicker?"
        self.label.textColor = .red
        self.label.font = UIFont.systemFont(ofSize: 20)
    }
}

@IBAction func didTapRev() {
    animateAsCustom {
        self.label.numberOfLines = 0
        self.label.text = "Hello this\nis animation !!!"
        self.label.textColor = .black
        self.label.font = UIFont.systemFont(ofSize: 30)
    }
}

如果您在上一个动画完成之前按下其中一个按钮,这仍然无法解决问题。要解决这个问题,可能还需要一些额外的努力。但是现在这个解决方案就足够了。

【讨论】:

  • 太棒了!这完美地工作。谢谢你的回答。我还发现我报告的问题主要与 iOS 14+ 有关。虽然动画在 iOS 12 中运行良好。
猜你喜欢
  • 1970-01-01
  • 2015-05-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多