动画 tableview 高度约束,但动画正在跳跃

Posted

技术标签:

【中文标题】动画 tableview 高度约束,但动画正在跳跃【英文标题】:Animating tableview height constraint but animation is jumping 【发布时间】:2018-07-23 03:59:25 【问题描述】:

我想为我拥有的 tableview 的高度约束设置动画。我已经建立了一个小型测试项目。表格视图位于容器视图中。

我的代码是这样的:

import UIKit

class ViewController: UIViewController 


    @IBOutlet weak var tableView: UITableView!
    @IBOutlet weak var heightConstraint: NSLayoutConstraint!
    @IBOutlet weak var contentView: UIView!

    override func viewDidLoad() 
        super.viewDidLoad()
        tableView.delegate = self
        tableView.dataSource = self
    

    @IBAction func didTapAnimate(_ sender: Any) 
        heightConstraint.constant = 400
        UIView.animate(withDuration: 1.0, animations: () in
            self.contentView.layoutIfNeeded()
        )
    



extension ViewController: UITableViewDataSource 

    func numberOfSections(in tableView: UITableView) -> Int 
        return 1
    

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
        return 3
    



extension ViewController: UITableViewDelegate 

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
        let cell = UITableViewCell()
        cell.backgroundColor = UIColor.red
        return cell
    

    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat 
        return 50
    


问题是,当我点击动画按钮时,动画不会顺利进行。桌子首先跳到一定高度,然后为其余部分设置动画。此处示例:

我在这里做错了什么?为什么桌子会跳?我需要动画流畅。对此的任何提示或指示将不胜感激!谢谢!

【问题讨论】:

试试这个:***.com/questions/49193750/… 您能描述一下内容视图约束吗?简而言之,从表视图中移除顶部约束。当您更改高度时,表格视图会识别冲突的约束。 @Kex 将此行 self.contentView.layoutIfNeeded() 更改为 self.view.layoutIfNeeded() 并且您的动画效果完美 如果@chiragshah 所说的不起作用,请显示约束。 @chiragshah 我告诉他你的解决方案应该有效。如果不是,他应该分享他的自动布局代码。 【参考方案1】:

所以您的问题不在于动画,而在于重新加载 UITableView。表格视图仅包含可见单元格,并且它会加载一个额外的单元格,该单元格大约等于顶部和底部的单元格高度。但是您的身高增长得如此之多,以至于它必须重新加载以保持可见的单元格,从而使重新加载和表格看起来很跳跃。所以我将如何解决这个问题是首先从 tableview 的顶部添加一个额外的约束到底部的安全区域插入,它与你的高度约束成反比。您将在一分钟内了解原因 这是它的样子。抱歉,我离开了内容视图,但它应该都可以正常工作..

这是整个设置的图像。

现在是代码和技巧。诀窍是当使 tableview 更大时,您首先在没有动画的情况下执行此操作,但不要将其向上移动。然后为我们刚刚添加的顶部约束设置动画,使其等于 -height。这样用户就看不到重新加载,但看起来它向上增长。要使其更小,请将其向下移动,然后更改大小,以便用户永远不会看到重新加载。这是代码,我添加了 cmets 以帮助您理解我在说什么。

import UIKit

class ViewController: UIViewController 


    @IBOutlet weak var topTableConstraint: NSLayoutConstraint!
    @IBOutlet weak var tableView: UITableView!
    @IBOutlet weak var heightConstraint: NSLayoutConstraint!

    override func viewDidLoad() 
        super.viewDidLoad()
        tableView.delegate = self
        tableView.dataSource = self
    

    @IBAction func didTapAnimate(_ sender: Any) 

        if heightConstraint.constant != 400
            //first change the height.  The thing that will happen is allow the tableview to load up all of it's rows and will stop the choppy ness
            heightConstraint.constant = 400
            self.view.layoutIfNeeded()
            //now we can move it up and it will appear to grow.
            //with iphone x i would put a view in inside the safearaa above the table as to now see it slide up or load underneath or you could pin your content view to the safe area and clip to bounds and this would work as well
            topTableConstraint.constant = -heightConstraint.constant
            UIView.animate(withDuration: 1.0) 
                self.view.layoutIfNeeded()
            
        else
           //animating down so let's do the reverse order
            topTableConstraint.constant = -100
            UIView.animate(withDuration: 1.0, animations: 
                self.view.layoutIfNeeded()
            )  (finished) in
                self.heightConstraint.constant = 100
                self.view.layoutIfNeeded()
            
        
    



extension ViewController: UITableViewDataSource 

    func numberOfSections(in tableView: UITableView) -> Int 
        return 1
    

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
        return 3
    



extension ViewController: UITableViewDelegate 

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
        let cell = UITableViewCell()
        cell.backgroundColor = UIColor.red
        return cell
    

    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat 
        return 50
    


结果将如下所示。希望这有助于并解释问题并为您解决问题。

此外,如果您希望所有单元格都为红色,那么您需要注册一个单元格,即使用 dequeueReusableCell 而不是创建一个新单元格。

【讨论】:

谢谢。现在工作!【参考方案2】:

因为你使用了height Constraint.constant = 400,所以height是为了使更大,你需要使用约束位置'Y'并移动到位置Y

  UIView.animate(withDuration: 1.0, animations: 
        self.yourTable.frame = CGRect(x: self.yourTable.frame.origin.x, y: self.view.frame.height - self.yourTable.frame.height - <Where do you want go>, width: self.yourTable.frame.width, height: self.yourTable.frame.height) 
    )

【讨论】:

【参考方案3】:

添加到tableview 的约束在您的方案中存在冲突。检查storyboard

我使用了与你相同的代码:

@IBAction func methodAnimate(_ sender: Any) 
    heightConstraint.constant = 400
    UIView.animate(withDuration: 1.0, animations: () in
        self.contentView.layoutIfNeeded()
    )

有这些限制:

动画效果很好。

【讨论】:

以上是关于动画 tableview 高度约束,但动画正在跳跃的主要内容,如果未能解决你的问题,请参考以下文章

高度约束动画“跳跃”

约束动画之前的跳跃图像

自定尺寸单元格高度变化导致跳跃动画

动画 UIView 大小跳跃

约束动画问题

收缩高度约束动画问题