iphone - 是否可以使用UITableView tableHeaderView进行自动布局?

自从我发现CustomView后我到处使用它,现在我正在尝试使用UILabel

我做了CustomViewUILabel添加了一切(标签等...)我想要他们的约束,然后我将这个tableHeaderView添加到UITableView'tableHeaderView

一切正常,除了CustomView总是显示在UILabel之上,上面我的意思是tableHeaderView是在UITableView之下所以它无法看到!

似乎无论我做什么,UILabel'tableHeaderViewCustomView始终为0(宽度,x和y也是如此)。

我的问题:如果不手动设置框架,是否可以完成此操作?

编辑:我正在使用的CustomView'UILabel有这些限制:

_title = [[UILabel alloc]init];
_title.text = @"Title";
[self addSubview:_title];
[_title keep:[KeepTopInset rules:@[[KeepEqual must:5]]]]; // title has to stay at least 5 away from the supperview Top
[_title keep:[KeepRightInset rules:@[[KeepMin must:5]]]];
[_title keep:[KeepLeftInset rules:@[[KeepMin must:5]]]];
[_title keep:[KeepBottomInset rules:@[[KeepMin must:5]]]];

我正在使用一个方便的库'KeepLayout',因为手动编写约束需要永远和一个单一约束的方式太多,但方法是自我解释。

CustomView有这些限制:

_tableView = [[UITableView alloc]init];
_tableView.translatesAutoresizingMaskIntoConstraints = NO;
_tableView.delegate = self;
_tableView.dataSource = self;
_tableView.backgroundColor = [UIColor clearColor];
[self.view addSubview:_tableView];
[_tableView keep:[KeepTopInset rules:@[[KeepEqual must:0]]]];// These 4 constraints make the UITableView stays 0 away from the superview top left right and bottom.
[_tableView keep:[KeepLeftInset rules:@[[KeepEqual must:0]]]];
[_tableView keep:[KeepRightInset rules:@[[KeepEqual must:0]]]];
[_tableView keep:[KeepBottomInset rules:@[[KeepEqual must:0]]]];

_detailsView = [[CustomView alloc]init];
_tableView.tableHeaderView = _detailsView;

我不知道是否必须直接在CustomView上设置一些约束,我认为CustomView的高度取决于其中UILabel“title”的约束。

编辑2:经过另一次调查后,似乎正确计算了CustomView的高度和宽度,但CustomView的顶部仍然与UITableView的顶部处于同一级别,当我滚动时它们一起移动。

ItsASecret asked 2019-09-10T07:33:19Z
25个解决方案
123 votes

我在这里问了并回答了类似的问题。 总之,我添加了一次标题并使用它来查找所需的高度。 然后可以将该高度应用于标题,并且第二次设置标题以反映更改。

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.header = [[SCAMessageView alloc] init];
    self.header.titleLabel.text = @"Warning";
    self.header.subtitleLabel.text = @"This is a message with enough text to span multiple lines. This text is set at runtime and might be short or long.";

    //set the tableHeaderView so that the required height can be determined
    self.tableView.tableHeaderView = self.header;
    [self.header setNeedsLayout];
    [self.header layoutIfNeeded];
    CGFloat height = [self.header systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;

    //update the header's frame and set it again
    CGRect headerFrame = self.header.frame;
    headerFrame.size.height = height;
    self.header.frame = headerFrame;
    self.tableView.tableHeaderView = self.header;
}

如果您有多行标签,这也依赖于自定义视图设置每个标签的preferredMaxLayoutWidth:

- (void)layoutSubviews
{
    [super layoutSubviews];

    self.titleLabel.preferredMaxLayoutWidth = CGRectGetWidth(self.titleLabel.frame);
    self.subtitleLabel.preferredMaxLayoutWidth = CGRectGetWidth(self.subtitleLabel.frame);
}

或者更一般地说:

override func layoutSubviews() {
    super.layoutSubviews()  
    for view in subviews {
        guard let label = view as? UILabel where label.numberOfLines == 0 else { continue }
        label.preferredMaxLayoutWidth = CGRectGetWidth(label.frame)
    }
}

2015年1月更新

不幸的是,这仍然是必要的 这是布局过程的一个快速版本:

tableView.tableHeaderView = header
header.setNeedsLayout()
header.layoutIfNeeded()
header.frame.size = header.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize)
tableView.tableHeaderView = header

我发现将它移动到UITableView的扩展中很有用:

extension UITableView {
    //set the tableHeaderView so that the required height can be determined, update the header's frame and set it again
    func setAndLayoutTableHeaderView(header: UIView) {
        self.tableHeaderView = header
        header.setNeedsLayout()
        header.layoutIfNeeded()
        header.frame.size = header.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize)
        self.tableHeaderView = header
    }
}

用法:

let header = SCAMessageView()
header.titleLabel.text = "Warning"
header.subtitleLabel.text = "Warning message here."
tableView.setAndLayoutTableHeaderView(header)
Ben Packard answered 2019-09-10T07:34:12Z
24 votes

我一直无法使用约束(在代码中)添加标题视图。 如果我给我的视图一个宽度和/或一个高度约束,我得到一个崩溃的消息说:

 "terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Auto Layout still required after executing -layoutSubviews. UITableView's implementation of -layoutSubviews needs to call super."

当我将故事板中的视图添加到我的表视图时,它没有显示任何约束,并且它作为标题视图工作正常,所以我认为标题视图的放置不是使用约束完成的。 在这方面,它似乎不像普通的观点。

宽度自动是表格视图的宽度,您需要设置的唯一内容是高度 - 原点值被忽略,因此您为这些放置的内容无关紧要。 例如,这个工作正常(对于rect来说也是0,0,0,80):

UIView *headerview = [[UIView alloc] initWithFrame:CGRectMake(1000,1000, 0, 80)];
headerview.backgroundColor = [UIColor yellowColor];
self.tableView.tableHeaderView = headerview;
rdelmar answered 2019-09-10T07:34:51Z
11 votes

我在这里看到很多方法做了很多不必要的东西,但是你不需要在标题视图中使用自动布局那么多。 你只需要创建你的xib文件,把你的约束和实例化如下:

func loadHeaderView () {
        guard let headerView = Bundle.main.loadNibNamed("CourseSearchHeader", owner: self, options: nil)?[0] as? UIView else {
            return
        }
        headerView.autoresizingMask = .flexibleWidth
        headerView.translatesAutoresizingMaskIntoConstraints = true
        tableView.tableHeaderView = headerView
    }
Ramon Vasconcelos answered 2019-09-10T07:35:16Z
6 votes

另一个解决方案是将标题视图创建分配给下一个主线程调用:

- (void)viewDidLoad {
    [super viewDidLoad];

    // ....

    dispatch_async(dispatch_get_main_queue(), ^{
        _profileView = [[MyView alloc] initWithNib:@"MyView.xib"];
        self.tableView.tableHeaderView = self.profileView;
    });
}

注意:当加载的视图具有固定高度时,它会修复错误。 当标题高度仅取决于其内容时,我还没有尝试过。

编辑:

您可以通过实现此功能找到更清晰的解决方案,并在viewDidLayoutSubviews中调用它

- (void)viewDidLayoutSubviews {
    [super viewDidLayoutSubviews];

    [self sizeHeaderToFit];
}
Martin answered 2019-09-10T07:36:02Z
3 votes

码:

  extension UITableView {

          func sizeHeaderToFit(preferredWidth: CGFloat) {
            guard let headerView = self.tableHeaderView else {
              return
            }

            headerView.translatesAutoresizingMaskIntoConstraints = false
            let layout = NSLayoutConstraint(
              item: headerView,
              attribute: .Width,
              relatedBy: .Equal,
              toItem: nil,
              attribute:
              .NotAnAttribute,
              multiplier: 1,
              constant: preferredWidth)

            headerView.addConstraint(layout)

            let height = headerView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize).height
            headerView.frame = CGRectMake(0, 0, preferredWidth, height)

            headerView.removeConstraint(layout)
            headerView.translatesAutoresizingMaskIntoConstraints = true

            self.tableHeaderView = headerView
          }
  }
Phil answered 2019-09-10T07:36:23Z
3 votes

发生了奇怪的事情。 systemLayoutSizeFittingSize适用于iOS9,但在我的情况下不适用于iOS 8。 所以这个问题很容易解决。 只需通过插入高度为CGRectGetMaxY(yourview.frame)+ padding,在超级调用更新标题视图边界后获取标题和viewDidLayoutSubviews中的底部视图的链接

UPD:有史以来最简单的解决方案:因此,在标题视图中放置子视图并将其固定为左,右,顶部。 在该子视图中,您的子视图会出现自动高度限制。 之后,将所有工作交给自动布局(无需计算)

- (void)viewDidLayoutSubviews {
    [super viewDidLayoutSubviews];

    CGFloat height = CGRectGetMaxY(self.tableView.tableHeaderView.subviews.firstObject.frame);
    self.tableView.tableHeaderView.bounds = CGRectMake(0, 0, CGRectGetWidth(self.tableView.bounds), height);
    self.tableView.tableHeaderView = self.tableView.tableHeaderView;
}

因此,子视图正在扩展/缩小,就像它应该一样,最后它调用viewDidLayoutSubviews。 当我们知道视图的实际大小时,所以设置headerView高度并通过重新分配来更新它。奇迹般有效!

也适用于页脚视图。

HotJard answered 2019-09-10T07:37:09Z
2 votes

您可以使用systemLayoutSizeFittingSize方法获取autolayout以提供大小。

然后,您可以使用它为您的应用程序创建框架。 只要您需要知道内部使用autolayout的视图的大小,此技术就可以使用。

swift中的代码看起来像

//Create the view
let tableHeaderView = CustomTableHeaderView()

//Set the content
tableHeaderView.textLabel.text = @"Hello world"

//Ask auto layout for the smallest size that fits my constraints    
let size = tableHeaderView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize)

//Create a frame    
tableHeaderView.frame = CGRect(origin: CGPoint.zeroPoint, size: size)

//Set the view as the header    
self.tableView.tableHeaderView = self.tableHeaderView

或者在Objective-C中

//Create the view
CustomTableHeaderView *header = [[CustomTableHeaderView alloc] initWithFrame:CGRectZero];

//Set the content
header.textLabel.text = @"Hello world";

//Ask auto layout for the smallest size that fits my constraints
CGSize size = [header systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];

//Create a frame
header.frame = CGRectMake(0,0,size.width,size.height);

//Set the view as the header  
self.tableView.tableHeaderView = header

还应注意,在此特定实例中,在子类中覆盖requiresConstraintBasedLayout会导致执行布局传递,但是此布局传递的结果将被忽略,系统框架将设置为tableView的宽度和0高度。

Jonathan answered 2019-09-10T07:38:02Z
2 votes

以下对我有用。

  1. 使用普通旧UITableView作为标题视图。
  2. 添加子视图到UITableView
  3. 在子视图上使用autolayout

我看到的主要好处是限制帧计算。 Apple应该真正更新UITableView的API以使其更容易。

使用SnapKit的示例:

let layoutView = UIView(frame: CGRect(x: 0, y: 0, width: tableView.bounds.width, height: 60))
layoutView.backgroundColor = tableView.backgroundColor
tableView.tableHeaderView = layoutView

let label = UILabel()
layoutView.addSubview(label)
label.text = "I'm the view you really care about"
label.snp_makeConstraints { make in
    make.edges.equalTo(EdgeInsets(top: 10, left: 15, bottom: -5, right: -15))
}
David Nix answered 2019-09-10T07:39:00Z
2 votes

针对表格页脚视图扩展此解决方案[http://collindonnell.com/2015/09/29/dynamically-sized-table-view-header-or-footer-using-auto-layout/]:

@interface AutolayoutTableView : UITableView

@end

@implementation AutolayoutTableView

- (void)layoutSubviews {
    [super layoutSubviews];

    // Dynamic sizing for the header view
    if (self.tableHeaderView) {
        CGFloat height = [self.tableHeaderView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
        CGRect headerFrame = self.tableHeaderView.frame;

        // If we don't have this check, viewDidLayoutSubviews() will get
        // repeatedly, causing the app to hang.
        if (height != headerFrame.size.height) {
            headerFrame.size.height = height;
            self.tableHeaderView.frame = headerFrame;
            self.tableHeaderView = self.tableHeaderView;
        }

        [self.tableHeaderView layoutIfNeeded];
    }

    // Dynamic sizing for the footer view
    if (self.tableFooterView) {
        CGFloat height = [self.tableFooterView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
        CGRect footerFrame = self.tableFooterView.frame;

        // If we don't have this check, viewDidLayoutSubviews() will get
        // repeatedly, causing the app to hang.
        if (height != footerFrame.size.height) {
            footerFrame.size.height = height;
            self.tableFooterView.frame = footerFrame;
            self.tableFooterView = self.tableFooterView;
        }

        self.tableFooterView.transform = CGAffineTransformMakeTranslation(0, self.contentSize.height - footerFrame.size.height);
        [self.tableFooterView layoutIfNeeded];
    }
}

@end
k06a answered 2019-09-10T07:39:26Z
1 votes

我的表头视图是一个UIView子类 - 我在初始化器中创建了一个contentView UIView,其边界与表头视图的框架相同,并将我的所有对象添加为其子视图。

然后在表标题视图的layoutSubviews方法中添加对象的约束,而不是在初始化程序中。 这解决了崩溃。

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:CGRectMake(0, 0, 0, 44.0)];
    if (self) {
        UIView *contentView = [[UIView alloc] initWithFrame:self.bounds];
        contentView.autoresizingMask = UIViewAutoresizingFlexibleWidth;

        // add other objects as subviews of content view

    }
    return self;
}

- (void)layoutSubviews
{
    [super layoutSubviews];

    // remake constraints here
}
Ryan answered 2019-09-10T07:39:59Z
1 votes

您可以在标题和tableview之间添加顶部+水平位置约束,以正确放置它(如果标题本身包含所有必要的内部布局约束以具有正确的帧)

在tableViewController中的viewDidLoad方法

    headerView.translatesAutoresizingMaskIntoConstraints = false

    tableView.tableHeaderView = headerView

    headerView.widthAnchor.constraint(equalTo: tableView.widthAnchor).isActive = true
    headerView.topAnchor.constraint(equalTo: tableView.topAnchor).isActive = true
    headerView.centerXAnchor.constraint(equalTo: tableView.centerXAnchor).isActive = true
GreatWiz answered 2019-09-10T07:40:33Z
1 votes

针对Swift 4.2进行了更新

extension UITableView {

    var autolayoutTableViewHeader: UIView? {
        set {
            self.tableHeaderView = newValue
            guard let header = newValue else { return }
            header.setNeedsLayout()
            header.layoutIfNeeded()
            header.frame.size = 
            header.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize)
            self.tableHeaderView = header
        }
        get {
            return self.tableHeaderView
        }
    }
}
Caleb Friden answered 2019-09-10T07:40:57Z
0 votes

我知道这是一个很老的帖子但经过所有关于这个的SO帖子并经过整整一个下午玩这个,我终于提出了一个干净但非常简单的解决方案

首先,我的视图层次结构如下所示:

  1. 表视图
    1. 查看3. View
      1. 使用名为headerView的插座查看

现在在View(No.3)中,我设置了所有约束,因为我通常将底部空间包含在容器中。 这将使容器(即3.View,即headerView)根据其子视图及其约束来调整自身大小。

之后,我将3. View2. View之间的约束设置为:

  1. 容器的顶部空间:0
  2. 容器的前导空间:0
  3. 到容器的尾随空格:0

请注意,我故意省略了底部空间。

一旦在故事板中完成所有这些操作,剩下要做的就是粘贴这三行代码:

if (self.headerView.frame.size.height != self.tableView.tableHeaderView.frame.size.height) {
    UIView *header = self.tableView.tableHeaderView;
    CGRect frame = self.tableView.tableHeaderView.frame;
    frame.size.height = self.headerView.frame.size.height + frame.origin.y;
    header.frame = frame;
    self.tableView.tableHeaderView = header;
}
Marc-Alexandre Bérubé answered 2019-09-10T07:42:36Z
0 votes

提示:如果你使用方法setAndLayoutTableHeaderView,你应该更新子视图的框架,所以在这种情况下UILabel的preferredMaxLayoutWidth应该在调用systemLayoutSizeFittingSize之前调用,不要在layoutSubview中调用。

代码秀

user1511613 answered 2019-09-10T07:43:08Z
0 votes

分享我的方法。

UITableView+XXXAdditions.m

- (void)xxx_setTableHeaderView:(UIView *)tableHeaderView layoutBlock:(void(^)(__kindof UIView *tableHeaderView, CGFloat *containerViewHeight))layoutBlock {
      CGFloat containerViewHeight = 0;
      UIView *backgroundView = [[UIView alloc] initWithFrame:CGRectZero];
      [backgroundView addSubview:tableHeaderView];
      layoutBlock(tableHeaderView, &containerViewHeight);

      backgroundView.frame = CGRectMake(0, 0, 0, containerViewHeight);

      self.tableHeaderView = backgroundView;
}

用法。

[self.tableView xxx_setTableHeaderView:myView layoutBlock:^(__kindof UIView * _Nonnull tableHeaderView, CGFloat *containerViewHeight) {
    *containerViewHeight = 170;

    [tableHeaderView mas_makeConstraints:^(MASConstraintMaker *make) {
      make.top.equalTo(@20);
      make.centerX.equalTo(@0);
      make.size.mas_equalTo(CGSizeMake(130, 130));
    }];
  }];
Vincent answered 2019-09-10T07:43:47Z
0 votes

在我的情况下,由于某种原因systemLayoutSizeFittingSize的方法不起作用。 对我有用的是对HotJard发布的解决方案的修改(他的原始解决方案在iOS 8中也不起作用)。 我需要做的是在标题视图中放置一个子视图并将其固定到左,右,顶部(不要固定到底部)。 在子视图中使用autolayout放置所有内容,并在代码中执行以下操作:

- (void)viewDidLayoutSubviews
{
    [super viewDidLayoutSubviews];
    [self resizeHeaderToFitSubview];
}

- (void)resizeHeaderToFitSubview
{
    UIView *header = self.tableView.tableHeaderView;
    [header setNeedsLayout];
    [header layoutIfNeeded];
    CGFloat height = CGRectGetHeight(header.subviews.firstObject.bounds);
    header.bounds = CGRectMake(0, 0, CGRectGetWidth(self.tableView.bounds), height);
    self.tableView.tableHeaderView = nil;
    self.tableView.tableHeaderView = header;
}
Leszek Szary answered 2019-09-10T07:44:14Z
0 votes

一个老帖子。 但是一个好帖子。 这是我的2美分。

首先,确保您的标题视图已排列其约束,以便它可以支持它自己的内在内容大小。 然后执行以下操作。

//ViewDidLoad
headerView.translatesAutoresizingMaskIntoConstraints = false
headerView.configure(title: "Some Text A")

//Somewhere else
headerView.update(title: "Some Text B)

private var widthConstrained = false

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    if widthConstrained == false {
        widthConstrained = true
        tableView.addConstraint(NSLayoutConstraint(item: headerView, attribute: .width, relatedBy: .equal, toItem: tableView, attribute: .width, multiplier: 1, constant: 0))
        headerView.layoutIfNeeded()
        tableView.layoutIfNeeded()
    }
}

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
    super.viewWillTransition(to: size, with: coordinator)
    coordinator.animate(alongsideTransition: { (context) in
        self.headerView.layoutIfNeeded()
        self.tableView.layoutIfNeeded()
    }, completion: nil)
}
answered 2019-09-10T07:44:47Z
0 votes

我能够通过以下方法实现它(这适用于页脚相同的方式)。

首先,您需要小型requiresConstraintBasedLayout分机:

斯威夫特3

extension UITableView {
    fileprivate func adjustHeaderHeight() {
        if let header = self.tableHeaderView {
            adjustFrame(header)
        }
    }

    private func adjustFrame(_ view: UIView) {
        view.frame.size.height = calculatedViewHeight(view)
    }

    fileprivate func calculatedHeightForHeader() -> CGFloat {
        if let header = self.tableHeaderView {
            return calculatedViewHeight(header)
        }
        return 0.0
    }

    private func calculatedViewHeight(_ view: UIView) -> CGFloat {
        view.setNeedsLayout()
        let height = view.systemLayoutSizeFitting(UILayoutFittingCompressedSize).height
        return height
    }
}

在您的视图控制器类实现中:

// this is a UIView subclass with autolayout
private var headerView = MyHeaderView()

override func loadView() {
    super.loadView()
    // ...
    self.tableView.tableHeaderView = headerView
    self.tableView.sectionHeaderHeight = UITableViewAutomaticDimension
    // ...
}

override func viewWillLayoutSubviews() {
    super.viewWillLayoutSubviews()

    // this is to prevent recursive layout calls
    let requiredHeaderHeight = self.tableView.calculatedHeightForHeader()
    if self.headerView.frame.height != requiredHeaderHeight {
        self.tableView.adjustHeaderHeight()
    }
}

关于标题requiresConstraintBasedLayout的子视图实现的注释:

  1. 您必须100%确定标题视图是否具有正确的自动布局设置。 我建议从只有一个高度约束的简单标题视图开始,然后尝试上面的设置。

  2. 覆盖requiresConstraintBasedLayout并返回true

class MyHeaderView: UIView {
   // ...
   override static var requiresConstraintBasedLayout : Bool {
       return true
   }
   // ...
}
Yevhen Dubinin answered 2019-09-10T07:45:52Z
0 votes

我的AutoLayout非常好用:

CGSize headerSize = [headerView systemLayoutSizeFittingSize:CGSizeMake(CGRectGetWidth([UIScreen mainScreen].bounds), 0) withHorizontalFittingPriority:UILayoutPriorityRequired verticalFittingPriority:UILayoutPriorityFittingSizeLevel];
headerView.frame = CGRectMake(0, 0, headerSize.width, headerSize.height);
self.tableView.tableHeaderView = headerView;
RomanV answered 2019-09-10T07:46:22Z
0 votes

对于Xamarin用户:

public override void ViewDidLayoutSubviews()
{
    base.ViewDidLayoutSubviews();

    TableviewHeader.SetNeedsLayout();
    TableviewHeader.LayoutIfNeeded();

    var height = TableviewHeader.SystemLayoutSizeFittingSize(UIView.UILayoutFittingCompressedSize).Height;
    var frame = TableviewHeader.Frame;
    frame.Height = height;
    TableviewHeader.Frame = frame;
}

假设您将tableview的标题视图命名为TableviewHeader

Gustavo Baiocchi Costa answered 2019-09-10T07:46:56Z
0 votes

您可以在UIViewController中使用以下链接

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    if headerView.frame.size.height == 0 {
      headerView.label.preferredMaxLayoutWidth = view.bounds.size.width - 20
      let height = headerView.systemLayoutSizeFitting(UILayoutFittingCompressedSize).height

      headerView.frame.size = CGSize(width: tableView.bounds.size.width, height: height)
    }
  }
onmyway133 answered 2019-09-10T07:47:23Z
0 votes

任何基于约束的tableFooterView都可以是一个很好的tableFooterView

需要先设置tableFooterView,然后在tableFooterViewtableHeaderView上施加额外的尾随约束。

- (void)viewDidLoad {

    ........................
    // let self.headerView is some constraint-based UIView
    self.tableView.tableFooterView = [UIView new];
    [self.headerView layoutIfNeeded];
    self.tableView.tableHeaderView = self.headerView;

    [self.tableView.leadingAnchor constraintEqualToAnchor:self.headerView.leadingAnchor].active = YES;
    [self.tableView.trailingAnchor constraintEqualToAnchor:self.headerView.trailingAnchor].active = YES;
    [self.tableView.topAnchor constraintEqualToAnchor:self.headerView.topAnchor].active = YES;
    [self.tableFooterView.trailingAnchor constraintEqualToAnchor:self.headerView.trailingAnchor].active = YES;

}

人们可以在这里找到所有细节和代码片段

malex answered 2019-09-10T07:48:08Z
0 votes

我找到了一个解决方法。 在空的uiview包装器中包装你的autolayout wrriten xib头视图,并将头视图分配给tableView的tableViewHeader属性。

    UIView *headerWrapper = [[UIView alloc] init];
    AXLHomeDriverHeaderView *headerView = [AXLHomeDriverHeaderView loadViewFromNib];
    [headerWrapper addSubview:headerView];
    [headerView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.edges.equalTo(headerWrapper);
    }];
    self.tableView.tableHeaderView = headerView;
tounaobun answered 2019-09-10T07:48:36Z
0 votes

这适用于ios 12中的UITableViewController,

将UIView放入TableView上面的所有原型单元格中以及页脚下的所有原型单元格。 根据需要设置页眉和页脚。 设置所有必需的约束。

现在使用以下扩展方法

public static class UITableVIewExtensions
{

    public static void MakeHeaderAutoDimension(this UITableView tableView)
    {
        if (tableView.TableHeaderView is UIView headerView) {
            var size = headerView.SystemLayoutSizeFittingSize(UIView.UILayoutFittingCompressedSize);
            if (headerView.Frame.Size.Height != size.Height) {
                var frame = headerView.Frame;
                frame.Height = size.Height;
                headerView.Frame = frame;
                tableView.TableHeaderView = headerView;
                tableView.LayoutIfNeeded();
            }
        }
    }

    public static void MakeFooterAutoDimension(this UITableView tableView)
    {
        if (tableView.TableFooterView is UIView footerView) {
            var size = footerView.SystemLayoutSizeFittingSize(UIView.UILayoutFittingCompressedSize);
            if (footerView.Frame.Size.Height != size.Height) {
                var frame = footerView.Frame;
                frame.Height = size.Height;
                footerView.Frame = frame;
                tableView.TableFooterView = footerView;
                tableView.LayoutIfNeeded();
            }
        }
    }
}

并在UITableViewController的子类的ViewDidLayoutSubviews中调用它

public override void ViewDidLayoutSubviews()
{
    base.ViewDidLayoutSubviews();

    TableView.MakeHeaderAutoDimension();
    TableView.MakeFooterAutoDimension();
}
HeisenBerg answered 2019-09-10T07:49:24Z
-1 votes

接受的答案仅对具有单个部分的表有用。 对于多部分UITableView,只需确保您的标题继承自contentView,您将没事。

作为替代方案,只需将您当前的标头嵌入contentViewcontentView中。完全像UITableViewCell的作品。

redent84 answered 2019-09-10T07:49:59Z
translate from https://stackoverflow.com:/questions/16471846/is-it-possible-to-use-autolayout-with-uitableviews-tableheaderview