有许多关于使用自动布局(one such thread)正确调整tableHeaderView大小的线程,但它们倾向于预先设置iOS 8。
我的情况有很多表格视图,都有标题,在iOS 7下正确大小但在iOS 8下使用大多数上述线程支持的代码不正确。在表的控制器中,我有以下方法:
- (void)rejiggerTableHeaderView
{
self.tableView.tableHeaderView = nil;
UIView *header = self.headerView;
[header setNeedsLayout];
[header layoutIfNeeded];
CGFloat height = [header systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
CGRect headerFrame = header.frame;
headerFrame.size.height = height;
header.frame = headerFrame;
self.tableView.tableHeaderView = header;
}
在iOS 7下使用多行标签,这样可以正确调整表格视图的标题大小:
但是在iOS 8下运行的相同代码会产生以下结果:
获取-systemLayoutSizeFittingSize的技巧是什么:在iOS 8下返回正确的大小? Here's a sample project证明了这个问题。
答案 0 :(得分:17)
将标题视图功能更改为以下内容适用于我:
- (void)rejiggerTableHeaderView
{
self.tableView.tableHeaderView = nil;
UIView *header = self.headerView;
CGRect frame = header.frame;
frame.size.width = self.tableView.frame.size.width;
header.frame = frame;
[header setNeedsLayout];
[header layoutIfNeeded];
CGFloat height = [header systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
CGRect headerFrame = header.frame;
headerFrame.size.height = height;
header.frame = headerFrame;
self.tableView.tableHeaderView = header;
}
答案 1 :(得分:14)
问题可以在非设定preferredMaxLayoutWidth
中。
如果您将其设置为更正UILabel宽度,它将正确确定约束。
您可以浏览标题中的所有UILabel
并将preferredMaxLayoutWidth
设置为标签宽度。
Swift 3示例:
extension UITableView {
public func relayoutTableHeaderView() {
if let tableHeaderView = tableHeaderView {
let labels = tableHeaderView.findViewsOfClass(viewClass: UILabel.self)
for label in labels {
label.preferredMaxLayoutWidth = label.frame.width
}
tableHeaderView.setNeedsLayout()
tableHeaderView.layoutIfNeeded()
tableHeaderView.frame.height = tableHeaderView.systemLayoutSizeFitting(UILayoutFittingCompressedSize).height
self.tableHeaderView = tableHeaderView
}
}
public func findViewsOfClass<T:UIView>(viewClass: T.Type) -> [T] {
var views: [T] = []
for subview in subviews {
if subview is T {
views.append(subview as! T)
}
views.append(contentsOf: subview.findViewsOfClass(viewClass: T.self))
}
return views
}
}
更新2:
如果您有具有宽高比约束的子视图并且同时与超视宽度约束成比例,则您可能会遇到高度计算不正确的问题
答案 2 :(得分:6)
由于这个问题已经有一年半了,所以这里是一个更新的完整版本,在Swift中。接受的答案中的一些代码是错误的或过时的。
func fixHeaderHeight() {
// Set your label text if needed
// ...
//
guard let header = tableView.tableHeaderView else {
return
}
let height = header.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize).height
header.frame.height = height
tableView.tableHeaderView = header
}
代码中的其他位置,您需要在标头中设置标签的preferredMaxLayoutWidth
。这应该等于tableView(或屏幕宽度)减去任何填充。标签出口的didSet
方法是一个好地方:
@IBOutlet weak var headerMessageLabel: UILabel! {
didSet {
headerMessageLabel.preferredMaxLayoutWidth = UIScreen.mainScreen().bounds.width - headerMessageLabelPadding
}
}
注意:如果接受的答案适合您,则表示您未正确使用大小类。
答案 3 :(得分:0)
如果标题只包含一个标签,那么我使用UILabel
扩展名来查找给定宽度的多行标签高度:
public extension UILabel {
public class func size(withText text: String, forWidth width: CGFloat) -> CGSize {
let measurementLabel = UILabel()
measurementLabel.text = text
measurementLabel.numberOfLines = 0
measurementLabel.lineBreakMode = .byWordWrapping
measurementLabel.translatesAutoresizingMaskIntoConstraints = false
measurementLabel.widthAnchor.constraint(equalToConstant: width).isActive = true
let size = measurementLabel.systemLayoutSizeFitting(UILayoutFittingCompressedSize)
return size
}
}
注意:以上是Swift 3语法。
使用上面计算的size
,您可以使用UITableViewDelegate
方法返回正确的高度:
func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat
答案 4 :(得分:0)
Swift 3中针对此问题的正确解决方案是使用此类而不是标准UILabel:
class UILabelPreferedWidth : UILabel {
override var bounds: CGRect {
didSet {
if (bounds.size.width != oldValue.size.width) {
self.setNeedsUpdateConstraints()
}
}
}
override func updateConstraints() {
if(preferredMaxLayoutWidth != bounds.size.width) {
preferredMaxLayoutWidth = bounds.size.width
}
super.updateConstraints()
}
}
另外请确保您没有在Cell类中禁用这两个:
translatesAutoresizingMaskIntoConstraints = false
contentView.translatesAutoresizingMaskIntoConstraints = false
答案 5 :(得分:0)
我遇到了同样的问题。 这适用于iOS 8.4。
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
[self.myLabel sizeToFit];
[self.tableView.tableHeaderView layoutIfNeeded];
return UITableViewAutomaticDimension;
}