使用自动布局,IB和字体大小时,表头视图高度是错误的

jed*_*xel 34 objective-c uitableview ios autolayout

我正在尝试为我的uiTableView创建一个标题视图(不是节标题,我已经有了.)我在界面构建器中设置了一个XIB.所有的连接都连接起来,它运行得很漂亮......除了桌子没有足够的空间!我的问题是表的顶部稍微重叠了表的标题.

我的XIB设置为所有按钮的自动布局,IB很高兴约束不会发生冲突/模糊.视图设置为自由形式大小,在我的情况下最终为320 x 471.然后在视图的约束中,我为视图设置了内在大小.

现在这与我的桌子完美搭配.一切看起来都很棒.但是如果我用代码手动更改标题视图中的任何字体,布局会使视图变大,最终会在我的表格下面.

任何想法如何让tableviewcontroller在设置字体和大小后留下足够的空间用于标题视图?我希望我有理由解释这一点.

vok*_*lam 65

注意:可以在这里找到Swift 3+版本:https://gist.github.com/marcoarment/1105553afba6b4900c10#gistcomment-1933639


这个想法是借助于计算标题的高度systemLayoutSizeFittingSize:targetSize.

返回满足其所包含约束的视图的大小.考虑到它所拥有的所有约束及其子视图的约束,确定视图的最佳大小.

更改标题高度后,必须重新分配tableHeaderView属性以调整表格单元格.

基于这个答案:在UITableView中使用自动布局来获得动态单元格布局和可变行高

- (void)sizeHeaderToFit
{
    UIView *header = self.tableView.tableHeaderView;

    [header setNeedsLayout];
    [header layoutIfNeeded];

    CGFloat height = [header systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
    CGRect frame = header.frame;

    frame.size.height = height;
    header.frame = frame;

    self.tableView.tableHeaderView = header;
}
Run Code Online (Sandbox Code Playgroud)

  • 对我来说绝对是完美的 - 我唯一没有在答案中看到的就是在哪里称之为.我在`viewDidLayoutSubviews`中调用了它,它对我有用. (4认同)
  • 这对我来说也适用于带有iOS 9.1的iPhone 6 Plus,但不适用于我的iPhone 5s iOS 8.0或iPhone 4s iOS 8.1.在viewDidLayoutSubviews中放置这个调用确实很奇怪,它继续递归地调用viewDidLayoutSubview ......并且将代码放在其他地方也不起作用,我把代码放在我认识的地方,在viewDidLayoutSubviews之后调用.有任何想法吗? (4认同)
  • 帮助我的是阅读和重新分配:`UIView*header = self.tableView.tableHeaderView;`和`self.tableView.tableHeaderView = header;`.我很好奇为什么. (2认同)
  • 有没有办法通过观察autolayout触发执行此代码,而不是直接从可能改变autolayout的所有地方调用此函数? (2认同)
  • @ClockWise当你使用`UITableViewController`时我发现了这种行为,因为每次设置tableView头时它都会再次调用layout.我建议切换到`UIViewController`并在其中嵌入`UITableView`,这将消除问题. (2认同)

rmi*_*eco 14

当我尝试将表视图标题设置为使用界面构建器使用自动布局定义的自定义视图时,我遇到了类似的问题.

当我这样做时,我会发现它会被一个节标题遮盖.

我的工作涉及使用"虚拟视图"作为表标题视图,然后将我的自定义视图作为子视图添加到该虚拟视图.我认为这允许自动布局根据约束和包含视图的框架配置外观.这可能不如vokilam的解决方案那么优雅,但它对我有用.


CGRect headerFrame = CGRectMake(0, 0, yourWidth, yourHeight);
UIView *tempView = [[UIView alloc] initWithFrame:headerFrame];
[tempView setBackgroundColor:[UIColor clearColor]];
YourCustomView *customView = [[YourCustomView alloc] initWithFrame: headerFrame];
[tempView addSubview:movieHeader];
self.tableView.tableHeaderView = tempView;
Run Code Online (Sandbox Code Playgroud)


may*_*yue 9

因为你tableHeaderView是inited形式xib,支持自动布局,让您的自定义的约束headerViewsuperView为unknown.You应该添加constraints自定义的headerView:

1.in viewDidLLoad您的自定义headerView分配到的tableView的tableHeaderView

 - (void)viewDidLoad
{
    [super viewDidLoad];
    UIView *yourHeaderView = [[[NSBundle mainBundle] loadNibNamed:@"yourHeaderView" owner:nil options:nil] objectAtIndex:0];
    //important:turn off the translatesAutoresizingMaskIntoConstraints;apple documents for details
     yourHeaderView.translatesAutoresizingMaskIntoConstraints = NO;
    self.tableView.tableHeaderView = yourHeaderView;
}
Run Code Online (Sandbox Code Playgroud)

2.in - (void)updateViewConstraints,添加自定义headerView的基本约束

- (void)updateViewConstraints
{
    NSDictionary *viewsDictionary = @{@"headerView":yourHeaderView};

    NSArray *constraint_V = [NSLayoutConstraint constraintsWithVisualFormat:@"V:[headerView(121)]"
                                                                    options:0
                                                                    metrics:nil
                                                                      views:viewsDictionary];

    NSArray *constraint_H = [NSLayoutConstraint constraintsWithVisualFormat:@"H:[headerView(320)]"
                                                                    options:0
                                                                    metrics:nil
                                                                      views:viewsDictionary];
    [self.headerView addConstraints:constraint_H];
    [self.headerView addConstraints:constraint_V];

    NSArray *constraint_POS_V = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[headerView]"
                                                                    options:0
                                                                    metrics:nil
                                                                      views:viewsDictionary];

    NSArray *constraint_POS_H = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[headerView]"
                                                                    options:0
                                                                    metrics:nil
                                                                      views:viewsDictionary];
    [self.tableView addConstraints:constraint_POS_V];
    [self.tableView addConstraints:constraint_POS_H];

    [super updateViewConstraints];
}
Run Code Online (Sandbox Code Playgroud)

好!PS:这是相关文档:调整视图控制器视图的大小


Clo*_*ise 7

是什么解决了我的问题:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    sizeHeaderToFit()
}

private func sizeHeaderToFit() { 
    if let headerView = tableView.tableHeaderView {

        headerView.setNeedsLayout()
        headerView.layoutIfNeeded()

        let height = headerView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize).height
        var newFrame = headerView.frame

        // Needed or we will stay in viewDidLayoutSubviews() forever
        if height != newFrame.size.height {
            newFrame.size.height = height
            headerView.frame = newFrame

            tableView.tableHeaderView = headerView
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我在某个地方找到了这个解决方案,并且像魅力一样工作,我记不清哪里了.


Mr *_*ers 5

我发现 vokilam 的答案非常有效。这是他在 Swift 中的解决方案。

func sizeHeaderToFit() {
    guard let header = tableView.tableHeaderView else { return }
    header.setNeedsLayout()
    header.layoutIfNeeded()
    let height = header.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize).height
    header.frame.size.height = height
    tableView.tableHeaderView = header
}
Run Code Online (Sandbox Code Playgroud)