动画化tableView的高度以使其适合屏幕上的内容

时间:2019-08-22 10:39:59

标签: ios swift uitableview

我正在构建嵌入在容器中的tableView叠加层。 主要目标是使tableView动画化其高度以使其适合屏幕上的内容。 经过长时间的试验和错误,我发现了以下但很棘手的方法:

1)当dataSource更改时,重新加载tableView。

2)更新viewDidLayoutSubviews()中的tableView的高度约束

3)在动画关闭时调用layoutIfNeeded()

4)设置回调容器的高度。

class VC: UIViewController {
    let tableView = UITableView()
        // This callback is used to updater overlayContainerView height to match tableView's contentSize height.
        public var layoutCallback: (_ value: CGFloat)->() = { _ in }

    var dataSource: ModalCardOverlayDataSource? = nil { didSet {
        tableView.dataSource = dataSource
        self.tableView.reloadData()
        view.setNeedsLayout()
        }

        .
        .
        .
        .

        override public func viewDidLayoutSubviews() {
            super.viewDidLayoutSubviews()
            self.tableView.snp.updateConstraints { make in
                make.height.equalTo(self.tableView.contentSize.height)
            }

            UIView.animate(withDuration: 0.3, animations: {
                self.view.layoutIfNeeded()
            })
            layoutCallback(tableView.contentSize.height)
        }
    }
}

该解决方案效果很好,但有一个缺点:每当高度保持不变时,视图就会向下动画,然后再次刷新时返回正确的高度。

当我删除动画代码时,不会发生此问题。我想这是UIKit固有的问题。

潜在的简便解决方法是引入其他变量来跟踪tableview的高度,当其保持不变时,将跳过动画代码。 但我想了解导致此问题的原因。

override public func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()

        print("the height is \(self.tableView.contentSize.height)")
        self.tableView.snp.updateConstraints { make in
            make.height.equalTo(self.tableView.contentSize.height)
        }

        UIView.animate(withDuration: 0.3, animations: {
            print("the height in animation is \(self.tableView.contentSize.height)")
            self.view.layoutIfNeeded()
        })
        print("the height in CALLBACK is \(self.tableView.contentSize.height)")
        layoutCallback(tableView.contentSize.height)
    }

当我在刷新具有相同内容的数据源时打印内容视图高度时,这就是我所得到的

初始值

  

高度为132.0动画中的高度为132.0高度为   132.0在动画中的高度是132.0在CALLBACK中的高度是275.33333587646484在CALLBACK中的高度是275.33333587646484在动画中的高度是275.33333587646484   275.33333587646484高度为275.3333333333333动画中的高度为275.3333333333333高度为275.3333333333333   动画中的高度为275.3333333333333回调中的高度为   275.3333333333333 CALLBACK中的高度为275.3333333333333 CALLBACK中的高度为275.3333333333333

第一次刷新:

  

高度为132.0动画中的高度为132.0高度为   132.0在动画中的高度是132.0在CALLBACK中的高度是275.33333587646484在CALLBACK中的高度是275.33333587646484

第二次刷新

  

高度为132.0,动画中的高度为132.0   CALLBACK是132.0的高度是275.33333587646484   动画是275.33333587646484高度是275.3333333333333的   动画中的高度为275.3333333333333,高度为   275.3333333333333动画中的高度为275.3333333333333 CALLBACK中的高度为275.3333333333333 CALLBACK中的高度为   275.3333333333333 CALLBACK中的高度为275.3333333333333高度为275.3333333333333动画中的高度为   275.3333333333333 CALLBACK中的高度为275.3333333333333

任何想法都可能导致这种奇怪的行为吗? 为什么动画代码根据重载是偶数还是奇数来使它在两个高度状态之间切换?

1 个答案:

答案 0 :(得分:0)

您需要创建表视图的子类,并在StoryBoard中使用自动布局。内部子类:-

import UIKit
class SelfSizingTableView: UITableView {

  override var intrinsicContentSize: CGSize {
      self.layoutIfNeeded()
      return self.contentSize
  }

  override var contentSize: CGSize {
     didSet{
        self.invalidateIntrinsicContentSize()
     }
  }
}

,还将tableview rowHeight设置为UITableViewAutomaticDimension。