【问题标题】:tableHeaderView on top of first cell第一个单元格顶部的 tableHeaderView
【发布时间】:2015-05-01 04:23:55
【问题描述】:

我正在尝试以编程方式创建一个 tableview,它在 tableHeaderView 中有一个搜索栏。出于某种原因,搜索栏出现在第一个单元格的顶部。

我正在使用 Masonry 来构建约束。

谁能指出我做错了什么。

- (void)setupViews {

...
    self.tableView = [[UITableView alloc] initWithFrame:CGRectZero];
    [self.view addSubview:self.tableView];

    self.searchBar = [[UISearchBar alloc] initWithFrame:CGRectZero];
    self.tableView.tableHeaderView = self.searchBar;
...
}

- (void)updateViewConstraints {

    [self.searchBar mas_updateConstraints:^(MASConstraintMaker *make) {
        make.width.equalTo(self.view);
        make.height.equalTo(@(44));
    }];

    [self.tableView mas_updateConstraints:^(MASConstraintMaker *make) {
        make.self.top.equalTo(self.view);
        make.self.bottom.equalTo(self.toolbar.mas_top);
        make.width.equalTo(self.view);
    }];
...
}

您可以在此处看到标题与单元格处于同一级别。

【问题讨论】:

  • 不错。 +1 视觉效果
  • 首先检查您的表格视图 Y 位置。可能是您的 TableView 标题位于导航栏的后面。检查标头是否实际创建?
  • 我做了一个小视频,让你可以看到tableview不在导航栏后面。 youtube.com/…

标签: ios objective-c uitableview autolayout masonry-ios-osx


【解决方案1】:

感谢您的帮助,我在 GitHub 上找到了一个关于使用 AutoLayout 更改 tableViewHeader 大小的要点:

https://gist.github.com/andreacremaschi/833829c80367d751cb83

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

    [headerView setNeedsLayout];
    [headerView layoutIfNeeded];
    CGFloat height = [headerView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;

    headerView.frame = ({
        CGRect headerFrame = headerView.frame;
        headerFrame.size.height = height;
        headerFrame;
    });

    self.tableHeaderView = headerView;
}

如果我在 updateViewConstraints 期间调用此方法,那么它可以工作。

但是,我并不完全理解它。

【讨论】:

  • 请在答案中发表评论
  • self.tableHeaderView = headerView;是关键。如果您不调用它,即使 tableHeaderView 高度发生变化,tableview 也不会重新定位包含单元格的视图。这会导致单元格显示在标题之外。
【解决方案2】:

在 Swift 3.0 中使用扩展

extension UITableView {

    func setTableHeaderView(headerView: UIView?) {
        // prepare the headerView for constraints
        headerView?.translatesAutoresizingMaskIntoConstraints = false

        // set the headerView
        tableHeaderView = headerView

        // check if the passed view is nil
        guard let headerView = headerView else { return }

        // check if the tableHeaderView superview view is nil just to avoid
        // to use the force unwrapping later. In case it fail something really
        // wrong happened
        guard let tableHeaderViewSuperview = tableHeaderView?.superview else {
            assertionFailure("This should not be reached!")
            return
        }

        // force updated layout
        headerView.setNeedsLayout()
        headerView.layoutIfNeeded()

        // set tableHeaderView width
        tableHeaderViewSuperview.addConstraint(headerView.widthAnchor.constraint(equalTo: tableHeaderViewSuperview.widthAnchor, multiplier: 1.0))

        // set tableHeaderView height
        let height = headerView.systemLayoutSizeFitting(UILayoutFittingCompressedSize).height
        tableHeaderViewSuperview.addConstraint(headerView.heightAnchor.constraint(equalToConstant: height))
    }

    func setTableFooterView(footerView: UIView?) {
        // prepare the headerView for constraints
        headerView?.translatesAutoresizingMaskIntoConstraints = false

        // set the footerView
        tableFooterView = footerView

        // check if the passed view is nil
        guard let footerView = footerView else { return }

        // check if the tableFooterView superview view is nil just to avoid
        // to use the force unwrapping later. In case it fail something really
        // wrong happened
        guard let tableFooterViewSuperview = tableFooterView?.superview else {
            assertionFailure("This should not be reached!")
            return
        }

        // force updated layout
        footerView.setNeedsLayout()
        footerView.layoutIfNeeded()

        // set tableFooterView width
        tableFooterViewSuperview.addConstraint(footerView.widthAnchor.constraint(equalTo: tableFooterViewSuperview.widthAnchor, multiplier: 1.0))

        // set tableFooterView height
        let height = footerView.systemLayoutSizeFitting(UILayoutFittingCompressedSize).height
        tableFooterViewSuperview.addConstraint(footerView.heightAnchor.constraint(equalToConstant: height))
    }
}

【讨论】:

  • 我必须添加 headerView.translatesAutoresizingMaskIntoConstraints = false 才能使其工作
  • 它们的关键是 layoutIfNeeded(),它强制同步布局循环,并再次设置页眉/页脚。
  • 只需在tableView.tableHeaderView = myView 之前添加myView.layoutIfNeeded() 即可正确完成这项工作。
【解决方案3】:

我认为问题是因为您正在使用autolayout 并手动将框架设置为视图,请替换此代码:

self.tableView = [[UITableView alloc] initWithFrame:CGRectZero];
[self.view addSubview:self.tableView];

self.searchBar = [[UISearchBar alloc] initWithFrame:CGRectZero];
self.tableView.tableHeaderView = self.searchBar;

类似这样的:

self.tableView = [UITableView new];
self.tableView.translatesAutoresizingMasksIntoConstraints = NO;
[self.view addSubview:self.tableView];

self.searchBar = [UISearchBar new];
self.searchBar.translatesAutoresizingMasksIntoConstraints = NO;
self.tableView.tableHeaderView = self.searchBar;

它可能不起作用,因为searchBar's框架可能需要手动设置,没有约束。

【讨论】:

    【解决方案4】:

    这里关于表格视图标题和表格视图单元格之间的空间问题。您可以使用属性检查器进行处理。请审查。 - 选择 UITableView - 在属性检查器 -> 滚动视图大小 -> 内容插入下,设置 Top = 44(或您的导航栏高度)。

    或者您可以通过编程方式处理它。

      - (void)viewDidLoad {
           UIEdgeInsets inset = UIEdgeInsetsMake(20, 0, 0, 0);
           self.tableView.contentInset = inset;
       }
    

    【讨论】:

    • 我正在以编程方式创建视图,因此 IB 不是一个选项
    猜你喜欢
    • 2021-08-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-10
    • 1970-01-01
    • 1970-01-01
    • 2015-12-16
    • 2014-01-17
    相关资源
    最近更新 更多