Swift 春季动画在 UITableViewCell 上无法正常工作

Posted

技术标签:

【中文标题】Swift 春季动画在 UITableViewCell 上无法正常工作【英文标题】:Swift spring animation is not working properly on a UITableViewCell 【发布时间】:2020-01-29 08:31:25 【问题描述】:

我已经阅读了一些关于 Swift 中弹簧动画的问题并且没有正确使用,但我对这个案例有点困惑。我有一个具有 UITableView 的 ViewController。我想在它的单元格中添加一些小的弹簧弹跳动画。当一个单元格被点击时,它应该会展开并运行弹跳动画,并且它第一次可以完美运行。但是在单元格被展开并再次点击后,动画被忽略了,但animations 中的代码正在完美运行(例如打印命令)。您是否有任何想法来实现使动画工作两次或更多的目标?我想我理论上错过了一些东西。

我的视图控制器:

class TestTableViewController: UIViewController 

    @IBOutlet weak var tableView: UITableView!

    var selectedIndex: IndexPath = IndexPath(row: 0, section: 0)

    var isExpanded = [Bool]()

    var currentExpandedIndexPath: IndexPath?


    override func viewDidLoad() 
        super.viewDidLoad()

        isExpanded = Array(repeating: false, count: 15)

        tableView.delegate = self
        tableView.dataSource = self

    


extension TestTableViewController: UITableViewDelegate, UITableViewDataSource 
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
        return 15
    

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
        let cell = tableView.dequeueReusableCell(withIdentifier: "TestTableViewCell", for: indexPath) as! TestTableViewCell

        cell.selectionStyle = .none
        cell.animate(duration: 0.5, delay: 0.2, damping: 0.5, options: .curveEaseOut)

        return cell
    

    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat 
        if isExpanded[indexPath.row] == true  return 300 
        return 150
    

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) 


        // This is just for handling that to be only one cell that is expanded at one time
        isExpanded[indexPath.row] = !isExpanded[indexPath.row]
        if (currentExpandedIndexPath != nil) 
            if (indexPath == currentExpandedIndexPath) 
                currentExpandedIndexPath = nil
             else 
                isExpanded[currentExpandedIndexPath!.row] = false
                currentExpandedIndexPath = indexPath
            
         else 
            currentExpandedIndexPath = indexPath
        

        tableView.beginUpdates()
        tableView.reloadRows(at: [indexPath], with: .automatic)
        tableView.endUpdates()
    

这是我的 TableViewCell 类:

class TestTableViewCell: UITableViewCell 

    func animate(duration: TimeInterval, delay: TimeInterval, damping: CGFloat, options: UIView.AnimationOptions = []) 

        UIView.animate(withDuration: duration, delay: delay, usingSpringWithDamping: damping, initialSpringVelocity: 1,  options: options, animations: 
            self.contentView.layoutIfNeeded()
            print("this command runs everytime")
        )
    


这些链接是 GIF,展示了它现在的工作方式。如果我在一个展开后点击另一个单元格,它有正确的动画(第一个链接)。但是如果我点击展开的那个,它就没有动画(第二个链接)。

Tapping one after one expanded

Tapping the same cell after it is expanded

【问题讨论】:

【参考方案1】:

这里有两种可能:

1 - 以下代码可能会覆盖您的动画:

tableView.reloadRows(at: [indexPath], with: .automatic)

尝试传递.none 或其他一些标志。

2 - 必须从主线程调用以下代码,也就是 DispatchQueue.main

self.contentView.layoutIfNeeded()

还有第三种可能性,reloadRows 不一定调用您当前正在处理动画的cellForRowAt

【讨论】:

不幸的是,第一种和第二种可能性都不起作用。我认为第三个是不可能的,因为 print 命令在 animate 方法中运行

以上是关于Swift 春季动画在 UITableViewCell 上无法正常工作的主要内容,如果未能解决你的问题,请参考以下文章

使用Swift中的Parse删除表视图单元格

2021年Scratch/C++/Python编程春季班招生

UITableView 自动布局定位

在执行代码之前等待 Swift 动画完成

Swift:沿动画路径动画对象

addSubview 在 swift 中破坏动画