简体   繁体   English

如何为隐藏在 UITableViewCell 中的 UIStackView 设置动画?

[英]How to animate UIStackView hiding inside UITableViewCell properly?

I want to animate the subviews of the TableViewCell which is StackView.我想为 StackView 的 TableViewCell 的子视图设置动画。 When I hide the StackView, the TableViewCell height not updating.当我隐藏 StackView 时,TableViewCell 高度不会更新。 After googling, I found that I should call tableView.beginUpdates and tableView.endUpdates to notify tableView that there is a change in the cell. google了之后发现应该调用tableView.beginUpdatestableView.endUpdates来通知tableView单元格有变化。 The problem is the hide animation and the change of tableview not sync.问题是隐藏动画和 tableview 的变化不同步。

Here is the view hierarchy for tableview cell这是 tableview 单元格的视图层次结构

Content view - Container View (for card shadow) - Container Stack View - [Stack View for label and switch] & [StudentStackView for container of StudentView]内容视图 - 容器视图(用于卡片阴影) - 容器堆栈视图 - [标签和开关的堆栈视图] & [StudentStackView 用于 StudentView 的容器]

How can I sync the cell height and hide animation the correct way?如何以正确的方式同步单元格高度并隐藏动画?

Here is the github repo: GitHub这是 github 存储库: GitHub

Gif of the App:应用程序的 Gif: UIStackView 动画与单元格高度不同步

You are right in using beginUpdates()/endUpdates() .您使用beginUpdates()/endUpdates()是正确的。 Make sure you're not placing the someArrangedSubview.isHidden = true/false in an animate block since the table view and stack view will handle the animations accordingly.确保您没有将someArrangedSubview.isHidden = true/false放在动画块中,因为表视图和堆栈视图将相应地处理动画。 When the table view begins update operations, the stack view will resize any arranged subviews that you aren't removing to fill the entire space of the cell (even if you have height constraints on the arranged subview).当表视图开始更新操作时,堆栈视图将调整您没有删除的任何排列的子视图的大小以填充单元格的整个空间(即使您对排列的子视图有高度限制)。 In my case, the cell content jumped every time I wanted to collapse a cell via removing an arranged subview--so I added a dummy view between the view I wished to remain static* and the collapsible view.就我而言,每次我想通过删除排列的子视图来折叠单元格时,单元格内容都会跳动——所以我在我希望保持静态* 的视图和可折叠视图之间添加了一个虚拟视图。 The static view won't resize, and the dummy view will expand/collapse as needed.静态视图不会调整大小,虚拟视图将根据需要展开/折叠。 Hope this helps.希望这可以帮助。

*static in the sense that I didn't want the view to move when animating. *静态,因为我不希望视图在动画时移动。

 `public func setup(classRoom: ClassRoom, toggleInProcess: @escaping () -> (), toggled: @escaping () -> ()) {
        containerStackView.addArrangedSubview(studentStackView)
        self.nameLabel.text = classRoom.name
        self.activeSwitch.isOn = classRoom.isActive
        self.studentStackView.isHidden = !self.activeSwitch.isOn // Let him know his hide/unhide. 
        for student in classRoom.students {
            let studentView = StudentView()
            studentView.nameLabel.text = student.name
            studentStackView.addArrangedSubview(studentView)
        }
        activeSwitch.addTarget(self, action: #selector(toggleShowStudents(show:)), for: .valueChanged)
        self.toggleInProcess = toggleInProcess
        self.toggled = toggled
        setupShadow()
    }`


`  @objc func toggleShowStudents(show: Bool) {
        UIView.animate(withDuration: 0.3, animations: {
            self.studentStackView.isHidden = !self.activeSwitch.isOn
            self.toggleInProcess()
            self.containerView.layoutIfNeeded()
        }) { _ in
            self.toggled()
        }
    }`

your studentStackView also know his hide/unhide status while assigning values in function setup .您的 studentStackView 在函数setup分配值时也知道他的隐藏/取消隐藏状态。

I left this as a comment but for anyone else experiencing this behavior, the root cause is the UILabel is expanding to fill the visible area before collapsing.我将此留作评论,但对于遇到此行为的其他任何人,根本原因是 UILabel 在折叠之前正在扩展以填充可见区域。

This can be fixed by doing the following 2 things:这可以通过执行以下两件事来解决:

  1. Right below the UILabel, insert a Blank UIView在 UILabel 正下方,插入一个空白 UIView
  2. Adjust the Content Hugging Priority of the UILabel to "Required"将 UILabel 的 Content Hugging Priority 调整为“Required”

With these two adjustments, instead of the UILabel expanding to fill the visible area, the UIView expands instead.通过这两个调整,而不是 UILabel 扩展以填充可见区域,而是 UIView 扩展。 Visually, this appears as if the the cell just collapses.从视觉上看,这看起来好像单元格刚刚折叠。

tableView.beginUpdates and tableView.endUpdates are functions that should be called when you are about to modify rowcount or selected state of the rows. tableView.beginUpdatestableView.endUpdates是当您将要修改行数或行的选定状态时应调用的函数。

You should try reloadData or reloadrowsatindexpaths , that should take care of the cell height adjustment.您应该尝试 reloadData 或reloadrowsatindexpaths ,它们应该负责单元格高度的调整。

You would better do it using performSelector API so as not to cause recursion in cellForRowAt call stack.您最好使用 performSelector API 来执行此操作,以免在cellForRowAt调用堆栈中引起递归。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM