如何用动画更改UITableView的宽度?

时间:2019-05-17 13:24:12

标签: ios swift uitableview animation

我的UITableView的左侧是UIView,右边是普通的UIViewController

  • UITableView连接到其中的.top.leading.bottom superview
  • UIView连接到其中的.top.trailing.bottom superview,也有.width
  • 还有UITableView .leading == .trailing中的UIView

您可以在屏幕截图上看到所有这些限制:

enter image description here

这是我在控制器中的动画代码,如您所见,我更新了.width的{​​{1}}并循环播放了动画。

UIView

因此,您可以在.gif上看到此内容,我应该如何进行平滑动画处理而又不出现毛刺?

enter image description here

4 个答案:

答案 0 :(得分:4)

更新

我尝试使用自己的UILabel子类重现UIView的错误行为:

class MyView: UIView {

    var currentSize: CGSize = .zero

    override func layoutSubviews() {
        super.layoutSubviews()
        guard currentSize != bounds.size else { return }
        currentSize = bounds.size
        setNeedsDisplay()
    }

    override func draw(_ rect: CGRect) {
        UIColor.purple.setFill()
        UIBezierPath(rect: rect).fill()
        let square = CGRect(x: rect.width - 50, y: rect.origin.y, width: 50, height: rect.height)
        UIColor.blue.setFill()
        UIBezierPath(rect: square).fill()
    }
}

该视图在其右侧绘制一个蓝色的小矩形作为文本。而且……嗯……动画也不错!

enter image description here

但是如果我将contentMode更改为left(默认值为scaleToFill

enter image description here

蓝色方块从一个地方跳到另一个地方。

因此,我发现这不仅与UILabel的{​​{1}}有关。它与textAlignment的默认left内容模式结合在一起。

UILabel定义了在内容大小和边界大小不同的情况下应如何调整内容-在动画制作中就是这种情况,在调整大小之前,视图会以新的大小重新绘制自己。

所以

contentMode

将表现为:

label.contentMode = .left // default
label.textAlignment = .left

上级答案

我花了一些时间解决您的问题。你猜怎么了?

它与表格视图完全无关。这是因为标签的label.contentMode = .right label.textAlignment = .right 文本对齐。

您可以使用简单的.right重现故障:

UILabel

为什么?

要找出错误,我创建了一个class ViewController: UIViewController { let label = UILabel() var rightConstraint: NSLayoutConstraint! override func loadView() { view = UIView() view.backgroundColor = .white } override func viewDidLoad() { super.viewDidLoad() setUpView() start() } func start() { DispatchQueue.main.asyncAfter(deadline: .now() + 3) { if self.rightConstraint.constant == 50 { self.change(width: 100) } else { self.change(width: 50) } self.start() } } func change(width: CGFloat) { rightConstraint.constant = width UIView.animate(withDuration: 1.0) { self.view.layoutIfNeeded() } } func setUpView() { label.text = "Label" label.textAlignment = .right view.addSubview(label) label.translatesAutoresizingMaskIntoConstraints = false rightConstraint = view.trailingAnchor.constraint(equalTo: label.trailingAnchor) rightConstraint.isActive = true label.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true label.topAnchor.constraint(equalTo: view.topAnchor).isActive = true label.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true label.topAnchor.constraint(equalTo: view.topAnchor).isActive = true } } 子类并覆盖了UILabel。这是每个action(for: CALayer, forKey: String)决定响应属性更改而应用哪个动画(ref)的地方。当标签位于表格视图中时,我一直在寻找一些奇怪的动画行为。

如果打印UIView,则会看到key即将提交与{{1 }}。

实际上,UIKit的每次更改都会调用UIView.animate(withDuration:)(这很有意义)。因此,我想标签的内容重绘与其框架更改之间存在冲突。

我认为您应该在不使用setNeedsDisplay的情况下重新创建标签的正确文本对齐方式。

水平将标签仅固定在右侧。调用UILabel时,只会更改标签的位置,而不会更改其内容。

答案 1 :(得分:1)

如@ {Gaétanz答案中所述。异常行为归因于单元内部的标签。

您可以通过将“标签”前导约束关系更改为> =来消除故障,并将优先级从1000更改为999。

请参考所附的屏幕截图,以供参考。

enter image description here

当添加优先级小于1000的约束时,它将是可选约束。优先级1000是约束所需的优先级。在这里,如果您添加了优先级999,所有其他优先级为1000的约束将首先布局,而优先级较低的约束将最后布局。

答案 2 :(得分:0)

您正在更改动画块外部的侧视图宽度。将widthConstaint.constant = width放到动画块中。

func change(width: CGFloat) {
      UIView.animate(withDuration: 1.0) {
            self.widthConstaint.constant = width
            self.view.layoutIfNeeded()
        }   
    }

答案 3 :(得分:0)

根据您的代码,将对View进行动画处理,但不会将约束放置在UIView动画块中。因此,它看起来像是小故障,导致直接更改了帧。请尝试如下更改代码,然后尝试。

func change(width: CGFloat) {
        UIView.animate(withDuration: 1.0) {
            widthConstaint.constant = width
            self.tableView.layoutIfNeeded()
            self.view.layoutIfNeeded()
        }   
    }