UIScrollView 中的 UITableView 使用自动布局

时间:2022-11-22
本文介绍了UIScrollView 中的 UITableView 使用自动布局的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

目前,我正在使用 UITableView 以及 UIScrollView 中包含的其他视图.我希望 UITableView 的高度与其内容高度相同.

为了使事情复杂化,我还插入/删除行以提供手风琴效果,以便当用户点击一行时,它将显示该行的更多详细信息.

我已经完成了插入/删除,但目前它没有更新作为其父视图的 UIScrollView,以便重新计算 UIScrollView 的内容大小和 UITableViewUIScrollView 中的其他视图一起正确显示.

当我更改 UITableView 的内容时,我该如何实现这一点,以便调整 UIScrollView 的大小并正确布局其内容?我目前正在使用自动布局.

解决方案

首先,那些其他视图(table view 的兄弟姐妹)是否严格地在 table view 的上方和下方?如果是这样,您是否考虑过让表格视图正常滚动,并将这些外部视图放在表格视图的页眉和页脚视图中?那么你就不需要滚动视图了.

其次,您可能需要阅读

滚动视图具有浅蓝色背景.顶部的红色标签和底部的蓝色标签是滚动视图中表格视图的兄弟.

这是我测试中视图控制器的完整源代码.没有xib文件.

#import "ViewController.h"#import "MyTableView.h"@interface ViewController() <UITableViewDataSource, UITableViewDelegate>@结尾@implementation 视图控制器-(无效)加载视图{UIView *view = [[UIView alloc] init];self.view = 视图;UIScrollView *scrollView = [[UIScrollView alloc] init];scrollView.translatesAutoresizingMaskIntoConstraints = NO;scrollView.backgroundColor = [UIColor cyanColor];[查看 addSubview:scrollView];UILabel *topLabel = [[UILabel alloc] init];topLabel.translatesAutoresizingMaskIntoConstraints = NO;topLabel.text = @"顶部标签";topLabel.backgroundColor = [UIColor redColor];[scrollView addSubview:topLabel];UILabel *bottomLabel = [[UILabel alloc] init];bottomLabel.translatesAutoresizingMaskIntoConstraints = NO;bottomLabel.text = @"底部标签";bottomLabel.backgroundColor = [UIColor blueColor];[scrollView addSubview:bottomLabel];UITableView *tableView = [[MyTableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain];tableView.translatesAutoresizingMaskIntoConstraints = NO;tableView.dataSource = 自我;tableView.delegate = self;[scrollView addSubview:tableView];UILabel *footer = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 200, 30)];footer.backgroundColor = [UIColor greenColor];footer.text = @"页脚";tableView.tableFooterView = 页脚;NSDictionary *views = NSDictionaryOfVariableBindings(scrollView, topLabel, bottomLabel, tableView);[查看添加约束:[NSLayoutConstraintconstraintsWithVisualFormat:@"V:|[scrollView]|"选项:0 指标:无意见:意见]];[查看添加约束:[NSLayoutConstraintconstraintsWithVisualFormat:@"H:|[scrollView]|"选项:0 指标:无意见:意见]];[查看添加约束:[NSLayoutConstraintconstraintsWithVisualFormat:@"V:|[topLabel][tableView][bottomLabel]|"选项:0 指标:无意见:意见]];[查看添加约束:[NSLayoutConstraintconstraintsWithVisualFormat:@"H:|[topLabel]|"选项:0 指标:无意见:意见]];[查看添加约束:[NSLayoutConstraintconstraintsWithVisualFormat:@"H:|-8-[tableView]-8-|"选项:0 指标:无意见:意见]];[查看添加约束:[NSLayoutConstraintconstraintWithItem:tableView 属性:NSLayoutAttributeWidthrelatedBy:NSLayoutRelationEqualtoItem:视图属性:NSLayoutAttributeWidth乘数:1 常数:-16]];[查看添加约束:[NSLayoutConstraintconstraintsWithVisualFormat:@"H:|[bottomLabel]|"选项:0 指标:无意见:意见]];}- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {返回 20;}- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"];如果(!单元格){cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"Cell"];}cell.textLabel.text = [NSString stringWithFormat:@"Row %d", indexPath.row];返回单元格;}@结尾

At the moment, I'm using a UITableView along with other views that are contained in a UIScrollView. I want the UITableView to have its height to be the same as its content height.

To complicate things, I'm also inserting / deleting rows to provide an accordion effect so that when the user taps on a row, it will show more detail for that row.

I've got the insert / deletion done, though at the moment it doesn't update the UIScrollView which is its superview so that the content size of the UIScrollView is recalculated and the UITableView along with other views in the UIScrollView are displayed correctly.

How can I go about implementing this so that UIScrollView's size is adjusted and its contents laid out correctly when I change the content of the UITableView? I'm currently using auto layout.

解决方案

First of all, are those other views (siblings of the table view) strictly above and below the table view? If so, have you considered letting the table view scroll normally, and putting those outside views in the table view's header and footer views? Then you don't need the scroll view.

Second, you may want to read Technical Note TN2154: UIScrollView And Autolayout if you haven't already.

Third, given the information in that tech note, I can think of a few ways to do what you want. The cleanest is probably to create a subclass of UITableView that implements the intrinsicContentSize method. The implementation is trivial:

@implementation MyTableView

- (CGSize)intrinsicContentSize {
    [self layoutIfNeeded]; // force my contentSize to be updated immediately
    return CGSizeMake(UIViewNoIntrinsicMetric, self.contentSize.height);
}

@end

Then just let auto layout use the table view's intrinsic content size. Create the constraints between the subviews of the scroll view (including the table view) to lay them out, and make sure there are constraints to all four edges of the scroll view.

You probably need to send invalidateIntrinsicContentSize to the table view at appropriate times (when you add or remove rows or change the heights of rows). You could probably just override the appropriate methods in MyTableView to do that. E.g. do [self invalidateIntrinsicContentSize] in -endUpdates, -reloadData, - insertRowsAtIndexPaths:withRowAnimation:, etc.

Here's the result of my testing:

The scroll view has the light blue background. The red top label and the blue bottom label are siblings of the table view inside the scroll view.

Here's the complete source code for the view controller in my test. There's no xib file.

#import "ViewController.h"
#import "MyTableView.h"

@interface ViewController () <UITableViewDataSource, UITableViewDelegate>

@end

@implementation ViewController

- (void)loadView {
    UIView *view = [[UIView alloc] init];
    self.view = view;

    UIScrollView *scrollView = [[UIScrollView alloc] init];
    scrollView.translatesAutoresizingMaskIntoConstraints = NO;
    scrollView.backgroundColor = [UIColor cyanColor];
    [view addSubview:scrollView];

    UILabel *topLabel = [[UILabel alloc] init];
    topLabel.translatesAutoresizingMaskIntoConstraints = NO;
    topLabel.text = @"Top Label";
    topLabel.backgroundColor = [UIColor redColor];
    [scrollView addSubview:topLabel];

    UILabel *bottomLabel = [[UILabel alloc] init];
    bottomLabel.translatesAutoresizingMaskIntoConstraints = NO;
    bottomLabel.text = @"Bottom Label";
    bottomLabel.backgroundColor = [UIColor blueColor];
    [scrollView addSubview:bottomLabel];

    UITableView *tableView = [[MyTableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain];
    tableView.translatesAutoresizingMaskIntoConstraints = NO;
    tableView.dataSource = self;
    tableView.delegate = self;
    [scrollView addSubview:tableView];

    UILabel *footer = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 200, 30)];
    footer.backgroundColor = [UIColor greenColor];
    footer.text = @"Footer";
    tableView.tableFooterView = footer;

    NSDictionary *views = NSDictionaryOfVariableBindings(
        scrollView, topLabel, bottomLabel, tableView);
    [view addConstraints:[NSLayoutConstraint
        constraintsWithVisualFormat:@"V:|[scrollView]|"
        options:0 metrics:nil views:views]];
    [view addConstraints:[NSLayoutConstraint
        constraintsWithVisualFormat:@"H:|[scrollView]|"
        options:0 metrics:nil views:views]];
    [view addConstraints:[NSLayoutConstraint
        constraintsWithVisualFormat:@"V:|[topLabel][tableView][bottomLabel]|"
        options:0 metrics:nil views:views]];
    [view addConstraints:[NSLayoutConstraint
        constraintsWithVisualFormat:@"H:|[topLabel]|"
        options:0 metrics:nil views:views]];
    [view addConstraints:[NSLayoutConstraint
        constraintsWithVisualFormat:@"H:|-8-[tableView]-8-|"
        options:0 metrics:nil views:views]];
    [view addConstraint:[NSLayoutConstraint
        constraintWithItem:tableView attribute:NSLayoutAttributeWidth
        relatedBy:NSLayoutRelationEqual
        toItem:view attribute:NSLayoutAttributeWidth
        multiplier:1 constant:-16]];
    [view addConstraints:[NSLayoutConstraint
        constraintsWithVisualFormat:@"H:|[bottomLabel]|"
        options:0 metrics:nil views:views]];
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return 20;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"];
    if (!cell) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"Cell"];
    }
    cell.textLabel.text = [NSString stringWithFormat:@"Row %d", indexPath.row];
    return cell;
}

@end

这篇关于UIScrollView 中的 UITableView 使用自动布局的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持html5模板网!

上一篇:UIScrollView contentSize 不起作用 下一篇:如何在 Interface Builder 中使用 UIScrollView?

相关文章

最新文章