ios - 在 Cell 的 UIStackView 中隐藏 subview 时动画很奇怪

标签 ios swift

情况是这样的。 stackView 中的标题标签、“阅读更多”按钮和内容标签。而stackView在一个cell中,设置Auto-Layout。 tableView 的单元格的高度设置为 AutoDimension。当我点击按钮时,内容标签将显示或隐藏。

按钮的 Action 方法是

@IBAction func readMore(_ sender: Any) {
  tableView.performBatchUpdates({
    self.contentLabel.isHidden.toggle()
  }, completion: nil)
}

这是慢速动画的结果:

enter image description here

可以看到,当要显示内容时,第2行最先显示,即内容从中心显示。当内容要隐藏时,内容标签立即隐藏,按钮被拉伸(stretch)到内容标签隐藏前的框架。这个动画很奇怪。

此外,如果我将 stackView 的间距设置为 10,情况会变得更糟。标题标签也受到影响:

enter image description here

我调整了一切,stackView 的分布,三个 subview 的内容模式和内容拥抱/压缩优先级。我找不到合适的方法来修复它。

这是理想的结果:

enter image description here

我通过一个小技巧实现了它:

@IBAction func readMore(_ sender: Any) {
  tableView.performBatchUpdates({
    UIView.animate(withDuration: 0.3) { // It must be 0.3
      self.contentLabel.isHidden.toggle()
    }
  }, completion: nil)
}

我不确定这是最合适的修复方法。所以我想知道为什么会出现这种奇怪的动画,以及是否有更合适的方法来修复它。谢谢!

最佳答案

隐藏/显示多行标签的动画可能会出现问题,特别是在堆栈 View 中使用时。

如果您尝试一下,您会发现即使在 TableView 单元格的外部 - 只是 View 中的堆栈 View - 在切换 时您也会看到同样的问题.isHidden 标签的属性。这是因为 UILabel 垂直居中它的文本。

这是另一种方法,它不使用堆栈 View (为清楚起见使用背景颜色):

enter image description here

Top Label设置为1行; Read More 是一个普通按钮,Bottom Label 设置为 0 行。

您会注意到粉红色的矩形。这是一个 UIView,我将其命名为 ShimView - 稍后会详细介绍。

顶部标签受到限制 顶部:4,前导:8,尾随:8 按钮受约束 Top:0(到 topLabel),Leading:8,Trailing:8 底部标签受到限制 Top: 0 (to button), Leading: 8, Trailing: 8

“垫片 View ”受到限制 尾随:8,顶部:0(*到底部标签的顶部*),底部:4(到 contentView)

“垫片 View ”给定了 21 的高度约束,优先级:999 -- 并且该高度约束已连接到单元格类中的 IBOutlet

关键是我们将调整 shim 的高度约束的 .constant 以展开/折叠单元格。

在初始化时,我们将 .constant 设置为 0 - 这将使 Bottom Label 保持在其内容确定的高度,但不会可见,因为它会被单元格的 contentView 裁剪。

当我们想要“显示/隐藏”标签时,我们将为垫片的高度 .constant 设置动画。

结果:

enter image description here

以及,清除背景色后的结果:

enter image description here

代码如下:

//
//  ExpandCollapseTableViewController.swift
//
//  Created by Don Mag on 6/19/18.
//

import UIKit

class ExpandCollapseCell: UITableViewCell {

    @IBOutlet var topLabel: UILabel!
    @IBOutlet var theButton: UIButton!
    @IBOutlet var bottomLabel: UILabel!
    @IBOutlet var theShim: UIView!
    @IBOutlet var shimHeightConstraint: NSLayoutConstraint!

    var myCallBack: (() -> ())?

    @IBAction func didTap(_ sender: Any) {
        myCallBack?()
    }

}

class ExpandCollapseTableViewController: UITableViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        tableView.rowHeight = UITableViewAutomaticDimension
        tableView.estimatedRowHeight = 100
    }

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

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 4
    }

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

        cell.topLabel.text = "Index Path - \(indexPath)"
        cell.bottomLabel.text = "Line 1\nLine 2\nLine 3\nLine 4"

        // init to "collapsed"
        // in actual use, this would be tracked so the row would remain expanded or collapsed
        // on reuse (when the table is scrolled)
        cell.shimHeightConstraint.constant = 0

        if true {
            cell.topLabel.backgroundColor = .clear
            cell.theButton.backgroundColor = .clear
            cell.bottomLabel.backgroundColor = .clear
            cell.theShim.backgroundColor = .clear
        }

        cell.myCallBack = {
            UIView.animate(withDuration: 0.3) { // It must be 0.3
                self.tableView.beginUpdates()
                cell.shimHeightConstraint.constant = (cell.shimHeightConstraint.constant == 0) ? cell.bottomLabel.frame.size.height : 0
                self.tableView.layoutIfNeeded()
                self.tableView.endUpdates()
            }
        }

        return cell
    }

}

关于ios - 在 Cell 的 UIStackView 中隐藏 subview 时动画很奇怪,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50930254/

相关文章:

ios - 防止调用静态库中的函数

arrays - 如何使用filter方法代替for in循环? swift

ios - 将 Int 附加到 [Int] 类型的集合会产生 'not identical' 错误

ios - 委托(delegate)属性(property)与协议(protocol)采用

ios - iOS应用提交时间过多

ios ipad uibutton 在键盘显示后无响应

ios - 使用工厂模式时如何将委托(delegate)设置为 View Controller ?

swift - 在 TableView - Swift 中创建的 7 个单元格之后添加部分

ios - NSAttributedString - 为阿拉伯语添加书写方向

ios - Swift:避免强制展开常量变量