UITableView标头在运行时的动态高度

时间:2017-05-26 07:28:16

标签: ios uitableview uiscrollview

我知道有很多关于它的帖子,但也许在最新的iOS上有一些更新...

我认为我们所有人都有创建viewController的任务,其中有很多内容位于顶部,其中大多数都是自我调整大小,最底层它表明你需要展示一些内容tableView有许多项目......

可以完成的第一个解决方案是使用UIScrollView,而根本不关心reusableCells。
是使用UITableView的{​​{1}}并在每次需要时手动调整其高度(或通过调用headerView)。
也许第三个解决方案是分别使用systemLayoutSizeFittingSize:和自定义UITableViewUIView上有UIEdgeInsets。并且取决于哪个对象具有更高的“zIndex”,它可能带来处理交互的问题...
第四解决方案是在单元格上方使用整个内容,就像单独的单元格一样。不确定这是一个好主意......

问题:这个问题有新的解决方案吗?我没有深入研究它2年......也许在新的iOS中有类似于tableView的reusableViews ...当然,目标是拥有可重复使用的单元格,并且使用自动布局的标题没有必要手动更新其高度...

8 个答案:

答案 0 :(得分:7)

我猜你在这里讨论表格视图的节标题。如果是这样的话,你绝对可以使用自动布局来处理章节标题。

viewDidLoad:

中使用以下两个代码
tableView.sectionHeaderHeight = UITableViewAutomaticDimension
tableView.estimatedSectionHeaderHeight = 36;

现在在viewForHeaderInSection:尝试以下代码,以了解事情是如何运作的。根据您的要求进行更改。

func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
    let label: UILabel = {
       let lb = UILabel()
        lb.translatesAutoresizingMaskIntoConstraints = false
        lb.text = "HEADER \(section) with a loooooooooooooooonnngngngngngngngng texxxxxxxxxxxxxxxxt"
        lb.textColor = .black
        lb.backgroundColor = .yellow
        lb.numberOfLines = 0
        return lb
    }()

    let header: UIView = {
        let hd = UIView()
        hd.backgroundColor = .blue
        hd.addSubview(label)
        label.leadingAnchor.constraint(equalTo: hd.leadingAnchor, constant: 8).isActive = true
        label.topAnchor.constraint(equalTo: hd.topAnchor, constant: 8).isActive = true
        label.trailingAnchor.constraint(equalTo: hd.trailingAnchor, constant: -8).isActive = true
        label.bottomAnchor.constraint(equalTo: hd.bottomAnchor, constant: -8).isActive = true
        return hd
    }()
    return header
}

答案 1 :(得分:2)

第一步:

从界面构建器拖动UIView并放入

UItableView 

此视图将自动充当UITableView标头(介意它不是节标题) 。假设此视图的宽度为200.如果您运行UItableView此视图将自动显示为标题。

创建此拖放视图的插座。

@property (weak, nonatomic) IBOutlet UIView *tableViewHeader; // height of this view is 200
  

现在我的目标是增加表View标题的高度。

第二步:

添加此方法

- (void)viewDidLayoutSubviews
{
int increasedHeight = 100;
// set a frame of this view Like example 
self.tableViewHeader.frame = CGRectMake(0, 0, self.view.frame.size.width , 200 + increasedHeight );

self.tableView.tableHeaderView = self.tableViewHeader;

}

现在你的tableview标题高度将是300。

答案 2 :(得分:1)

这就是我接触它的方式

使用tableview 我已经为XIB中的标题创建了UI

现在使用以下委托方法

func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {

}

我为标题创建一个UIView并根据内容计算高度并返回相同的内容。

现在我可以从以下委托方法返回相同的标题视图

func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {

}

基于该部分,我再次从xib创建一个视图,并从该方法返回该视图。

在我的情况下,我只需要一个表的标题视图,所以我保留了2个部分并返回第一部分的标题视图。

答案 3 :(得分:1)

如果您使用的是Interface Builder,则只需检查以下按钮 enter image description here

答案 4 :(得分:1)

useyourloaf.com复制

Swift 5.0

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    guard let headerView = tableView.tableHeaderView else {return}
    let size = headerView.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize)
    if headerView.frame.size.height != size.height {
        headerView.frame.size.height = size.height
        tableView.tableHeaderView = headerView
        tableView.layoutIfNeeded()
    }
}

答案 5 :(得分:0)

我喜欢在这里完成的方式:

•如果要基于其内容动态设置表格视图标题高度,只需在将headerView设置为TableViewHeader之后(即在self.tableView.layoutTableFooterView()之后)调用self.tableView.tableHeaderView = view

•如果您需要在运行时更新表视图标头的高度,请在更新表视图标头的值后立即调用self.tableView.layoutTableFooterView()

(显然,这也适用于tableviewFooters,但不用于 section Headers / Footers)

extension UITableView {

    //Variable-height UITableView tableHeaderView with autolayout
    func layoutTableHeaderView() {

        guard let headerView = self.tableHeaderView else { return }
        headerView.translatesAutoresizingMaskIntoConstraints = false

        let headerWidth = headerView.bounds.size.width
        let temporaryWidthConstraint = headerView.widthAnchor.constraint(equalToConstant: headerWidth)

        headerView.addConstraint(temporaryWidthConstraint)

        headerView.setNeedsLayout()
        headerView.layoutIfNeeded()

        let headerSize = headerView.systemLayoutSizeFitting(UILayoutFittingCompressedSize)
        let height = headerSize.height
        var frame = headerView.frame

        frame.size.height = height
        headerView.frame = frame

        self.tableHeaderView = headerView

        headerView.removeConstraint(temporaryWidthConstraint)
        headerView.translatesAutoresizingMaskIntoConstraints = true
    }

}

source

答案 6 :(得分:0)

我正在使用XCode 10.3,这是我的解决方案与使用表头视图的第二种解决方案一起使用的方法。

首先,您将使用xib文件(例如,内部带有标签)创建一个单独的视图。并将此标签的约束(上,左,下,右)应用于单元格的容器视图。并设置numberOfLines =0。
Example image
更新视图类中的awakeFromNib()函数。

override func awakeFromNib() {
    super.awakeFromNib()
    ourLabel.translatesAutoresizingMaskIntoConstraints = false
}

第二,在viewController上,设置tableView:

tableView.sectionHeaderHeight = UITableView.automaticDimension
tableView.estimatedSectionHeaderHeight = 64

请记住不要委派此方法:

func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat

因为我们已经设置了视图的约束。

最后,您通过委托方法

将其返回
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView?

标题视图。

let view = UINib(nibName: String(describing: SimpleHeaderTitleView.self), bundle: nil).instantiate(withOwner: nil, options: nil)[0] as! SimpleHeaderTitleView
 view.ourLabel.text = "Your longgggg text"
 return view



完成!检查它是否有效。

答案 7 :(得分:0)

您可以在包含您的 viewDidLayoutSubviewsUIViewController 中的 UITableView 中执行此操作:

@IBOutlet weak var tableView: UITableView!

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    // Resize header view with dynamic size in UITableView
    guard let headerView = tableView.tableHeaderView else {
        return
    }
    let size = headerView.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize)
    if headerView.frame.height != size.height {
        tableView.tableHeaderView?.frame = CGRect(
            origin: headerView.frame.origin,
            size: size
        )
        tableView.layoutIfNeeded()
    }
}