【问题标题】:UILabel size change doesn't animate with auto layoutUILabel 大小更改不使用自动布局进行动画处理
【发布时间】:2018-06-10 00:58:26
【问题描述】:

我有一个动态宽度UILabel(为可见性着色为石灰绿色),它对其邻居(绿色和红色视图)具有固定的前导和尾随约束。我希望这张桌子在它的一个邻居被移动时调整它的宽度(圆形的红色/绿色视图)。但是,由于我的标签的宽度在没有动画的情况下“跳转”到其新值,因此我对这种更改的动画有疑问。对于我的右对齐标签,这意味着文本本身也会跳跃。

我正在为红色/绿色视图的移动设置动画,如下所示:

- (void)show {
    self.edgeConstraint.constant = 0;
    [UIView animateWithDuration:0.25 animations:^{
        [self.contentView layoutIfNeeded];
    }];
}

- (void)hide {
    self.edgeConstraint.constant = -100;
    [UIView animateWithDuration:0.25 animations:^{
        [self.contentView layoutIfNeeded];
    }];
}

【问题讨论】:

  • 在设置约束之前调用layoutIfNeeded。然后在动画块内调用layoutIfNeeded(你已经在做这个了)。看看这是否有效。
  • 这个 gif 是你想要的还是问题???

标签: ios uiview autolayout uilabel uiviewanimation


【解决方案1】:

问题在于UILabel 内容模式。您会看到类似的问题here。因为您正在缩短绘制文本的标签,所以标签会执行一次绘制过程,但它使用动画块的最后一帧进行更新。创建平滑动画的最简单方法是使用greaterThanOrEqualTo 前导约束并将textAlignment 设置为.natural。

当我这样做时,我会得到顶部的结果,而不是在底部设置 textAlignment .right。

演示源代码:

import UIKit
import PlaygroundSupport

final class ViewController: UIViewController {

    var constraint: NSLayoutConstraint?
    var otherConstraint: NSLayoutConstraint?

    lazy private var sideView: UIView = {
        let view = UIView()
        view.translatesAutoresizingMaskIntoConstraints = false
        self.view.addSubview(view)
        view.topAnchor.constraint(equalTo: self.view.topAnchor).isActive = true
        self.constraint = view.leadingAnchor.constraint(equalTo: self.view.trailingAnchor)
        self.constraint?.isActive = true
        view.widthAnchor.constraint(equalToConstant: 100).isActive = true
        view.heightAnchor.constraint(equalToConstant: 44).isActive = true
        view.backgroundColor = .yellow
        return view
    }()

    lazy private var secondSideView: UIView = {
        let view = UIView()
        view.translatesAutoresizingMaskIntoConstraints = false
        self.view.addSubview(view)
        view.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 44.0).isActive = true
        self.otherConstraint = view.leadingAnchor.constraint(equalTo: self.view.trailingAnchor)
        self.otherConstraint?.isActive = true
        view.widthAnchor.constraint(equalToConstant: 100).isActive = true
        view.heightAnchor.constraint(equalToConstant: 44).isActive = true
        view.backgroundColor = .yellow
        return view
    }()

    lazy private var label: UILabel = {
        let label = UILabel()
        label.text = "Label"
        label.translatesAutoresizingMaskIntoConstraints = false
        self.view.addSubview(label)
        label.topAnchor.constraint(equalTo: self.view.topAnchor).isActive = true
        label.leadingAnchor.constraint(greaterThanOrEqualTo: self.view.leadingAnchor, constant: 8.0).isActive = true
        label.trailingAnchor.constraint(equalTo: self.sideView.leadingAnchor).isActive = true
        return label
    }()

    lazy private var secondLabel: UILabel = {
        let label = UILabel()
        label.textAlignment = .right
        label.text = "Label"
        label.translatesAutoresizingMaskIntoConstraints = false
        self.view.addSubview(label)
        label.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 44.0).isActive = true
        label.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: 8.0).isActive = true
        label.trailingAnchor.constraint(equalTo: self.sideView.leadingAnchor).isActive = true
        return label
    }()

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white
        self.secondSideView.isHidden = false
        self.secondLabel.isHidden = false
        self.sideView.isHidden = false
        self.label.isHidden = false
    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        self.perform(#selector(self.showSideView), with: nil, afterDelay: 5.0)
    }

    @objc private func showSideView() {
        self.view.layoutIfNeeded()
        UIView.animate(withDuration: 1.5, delay: 0.0, options: [.autoreverse, .repeat], animations: {
            self.otherConstraint?.constant = -100
            self.constraint?.constant = -100
            self.view.layoutIfNeeded()
        })
    }
}

PlaygroundPage.current.liveView = ViewController()

【讨论】:

  • 你说得对,问题在于文本重绘。一旦我开始阅读您的答案,我就记得我曾经遇到过这个问题,我最终使用了比例变换(在这种情况下,UILabel 的宽度和高度都被缩小了)。您使用“大于或等于”前导/尾随约束的建议完美地解决了这个问题。谢谢!
猜你喜欢
  • 1970-01-01
  • 2014-08-19
  • 2017-10-18
  • 1970-01-01
  • 2013-06-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多