使用AutoLayout的UITableView中的动态单元格高度 [英] dynamic cell height in UITableView with AutoLayout

查看:167
本文介绍了使用AutoLayout的UITableView中的动态单元格高度的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在试图获得这个教程动态细胞高度在ios8工作几天,无法弄清楚发生了什么。它在iPhone上的ios7中起作用,它在ios7和ios8在iPAD上,但它不适用于ios8上的任何iphone。



我认为问题在于如何以及何时在单元格中创建标签。



我在控制器中有以下代码:

   - ( void)viewDidLoad {
[super viewDidLoad];
//加载视图后执行任何其他设置。

self.dbManager = [[DBManager alloc] initWithDatabaseFilename:@tomhaisdb.sql];

[self loadData];

}

- (void)viewWillAppear:(BOOL)动画{
[super viewWillAppear:animated];
[self deselectAllRows];


- (void)deselectAllRows {
for(NSIndexPath * indexPath in [self.tableView indexPathsForSelectedRows]){
[self.tableView deselectRowAtIndexPath:indexPath animated:没有];
}
}

- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
//处理可以重新创建的任何资源。
}

- (void)loadData {
NSString * query = @从收藏夹中选择*;

if(self.favourites!= nil){
self.favourites = nil;
}

self.favourites = [[NSArray alloc] initWithArray:[self.dbManager loadDataFromDB:query]];

/ * [self reloadDataWithCompletions:^ {
self.tableView.backgroundColor = [UIColor colorWithRed:28.0f / 255.0f green:30.0f / 255.0f blue:35.0f / 255.0f alpha :1];
}]; * /
[self reloadTableViewContent];
}

- (void)reloadTableViewContent {
dispatch_async(dispatch_get_main_queue(),^ {
[self.tableView reloadData];
[self.tableView scrollRectToVisible:CGRectMake(0,0,1,1)动画:NO];
});
}

/ * - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;

#pragma mark - UITableViewDataSource

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSLog(@行数:%d,self.favourites.count);
return self.favourites.count;
}


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
return [self basicCellAtIndexPath:indexPath];
}

- (favouritedCell *)basicCellAtIndexPath:(NSIndexPath *)indexPath {
favouritedCell * cell = [self.tableView dequeueReusableCellWithIdentifier:@favouriteCellforIndexPath:indexPath];
[self configureBasicCell:cell atIndexPath:indexPath];
返回单元格;
}

- (void)configureBasicCell:(favouritedCell *)cell atIndexPath:(NSIndexPath *)indexPath {
NSInteger indexOfTomhaisText = [self.dbManager.arrColumnNames indexOfObject:@tomhaisText ];
NSString * tomhaisText = [[self.favourites objectAtIndex:indexPath.row] objectAtIndex:indexOfTomhaisText];
[self setTomhaisForCell:cell item:tomhaisText];
[self setAnswerForCell:cell item:tomhaisText]; //更改此文件
}

- (void)setTomhaisForCell:(favouritedCell *)单元格项目:(NSString *)项目{
[cell.favouriteText setText:item];
}

- (void)setAnswerForCell:(favouritedCell *)单元项:(NSString *)项{
[cell.answer setText:item];
}

#pragma mark - UITableViewDelegate

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
/ * if([[[UIDevice currentDevice] systemVersion] floatValue]> = 8.0){
return UITableViewAutomaticDimension;
}
else {* /
return [self heightForFavouriteCellAtIndexPath:indexPath];
/ *} * /

}

- (CGFloat)heightForFavouriteCellAtIndexPath:(NSIndexPath *)indexPath {
static favouritedCell * sizingCell = nil;
static dispatch_once_t onceToken;
dispatch_once(& onceToken,^ {
sizingCell = [self.tableView dequeueReusableCellWithIdentifier:@favouriteCell];
});

[self configureBasicCell:sizingCell atIndexPath:indexPath];
return [self calculateHeightForConfiguredSizingCell:sizingCell];
}

- (CGFloat)calculateHeightForConfiguredSizingCell:(UITableViewCell *)sizingCell {
sizingCell.bounds = CGRectMake(0.0f,0.0f,CGRectGetWidth(self.tableView.frame) CGRectGetHeight(sizingCell.bounds));
NSLog(@布局%@之前的边界,NSStringFromCGRect(sizingCell.bounds));
NSLog(@Content View before Layout%@,NSStringFromCGRect(sizingCell.contentView.bounds));
[sizingCell setNeedsLayout];
[sizingCell layoutIfNeeded];

CGSize size = [sizingCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];
NSLog(@布局%@之后的边界,NSStringFromCGRect(sizingCell.bounds));
NSLog(@Content View before Layout%@,NSStringFromCGRect(sizingCell.contentView.bounds));
return size.height + 1.0f;
}

- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath {
return 155.0f;
}

在自定义标签中,单元格使用我有以下内容:

  @implementation favouriteLabel 

- (void)setBounds:(CGRect)bounds {
[super setBounds :边界];

//如果这是一个多行标签,需要确保
// preferredMaxLayoutWidth总是匹配框架宽度
//(即方向更改可能会混乱)

if(self.numberOfLines == 0&& bounds.size.width!= self.preferredMaxLayoutWidth){
self.preferredMaxLayoutWidth = self.bounds.size.width;
NSLog(@更新约束之前的标签绑定%@,NSStringFromCGRect(self.bounds));
[self setNeedsUpdateConstraints];
NSLog(@更新约束后的标签绑定%@,NSStringFromCGRect(self.bounds));
}
}

@end

原因我认为我的问题在于创建标签时是因为在ios 7中,我得到如下输出:

  2015-06 -01 20:07:10.563事实[63322:607]更新约束之前的标签界限{{0,0},{216,2}} 
2015-06-01 20:07:10.563事实[63322:607 ]更新约束之后的标签边界{{0,0},{216,2}}
2015-06-01 20:07:10.563事实[63322:607]更新约束之前的标签边界{{0,0} ,{217,40}}
2015-06-01 20:07:10.563事实[63322:607]更新约束{{0,0},{217,40}}之后的标签边界
> ; 2015-06-01 20:07:10.564事实[63322:607]布局之后的界限{{0,0},{256,82}}
2015-06-01 20:07:10.564事实[63322 :607]布局前的内容视图{{0,0},{256,82}}
2015-06-01 20:07:10.564事实[63322:607]布局前{{0,0} {256,82}}
2015-06-01 20:07:10.564事实[63322:607]布局之前的内容视图{{0,0},{256,82}}
2015-06 -01 20: 07:10.565事实[63322:607]布局后的界限{{0,0},{256,82}}
2015-06-01 20:07:10.565事实[63322:607] {0,0},{256,82}}
2015-06-01 20:07:10.569事实[63322:607]更新约束{{0,0},{216,74.5}}之前的标签边界}
2015-06-01 20:07:10.569事实[63322:607]更新约束之后的标签边界{{0,0},{216,74.5}}
2015-06-01 20:07 :10.569 Facts [63322:607]更新约束之前的标签边界{{0,0},{217,40}}
2015-06-01 20:07:10.570事实[63322:607]更新后的标签边界约束{{0,0},{217,40}}

但是在ios8中输出是不同的。

  2015-06-01 20:18:06.049事实[63396:81689795]布局前的界限{{0,0} {256,44}} 
2015-06-01 20:18:06.049事实[63396:81689795]布局前的内容查看{{0,0},{320,44}}
2015-06 -01 20:18:06.131事实[63396:81689795]更新约束之前的标签边界{{0,0},{216,0}}
2015-06-01 20:18:06.131事实[63396:81689795 ]更新约束之后的标签边界{{0,0},{216,0}}
2015-06-01 20:18:06.131事实[63396:81689795]更新约束之前的标签边界{{0,0} ,{217,4.5}}
2015-06-01 20:18:06.131事实[63396:81689795]更新约束{{0,0},{217,4.5}}之后的标签边界

在ios7中,标签似乎首先被创建,然后是单元格边界,然后标签再次调整大小。但是在ios8中,我们首先看到内容视图输出,然后我们才能看到标签的输出。



很抱歉,我无法解释更好。对我来说这是一个谜,我如何使它的表,所以我真的坚持为什么它的工作在ios7而不是在ios8



任何帮助最感谢。我已经在这里写了这个问题:动态单元格高度自动布局IOS 但我认为我在这个问题上扔了一个关于autolayout的红色鲱鱼。

解决方案

框架错误地放置在答案标签上。由于没有为任何Xany安装标签,所以在Interface Builder中看不到警告。



由于约束不等于预期高度,因此停止自动布局正确解决iOS 8的单元格高度。



快速修复是勾选其任何的已安装框。你会看到警告显示。选择答案标签,选择编辑 - >自动出价问题 - >更新框架,你很好去!



更新: p>

标签最初显示的原因不需要重新加载,因为anyXany框被勾选。 Apple看到有安装的约束,初始高度是正确的,没有重新加载或滚动。



当没有勾选该框时,在布局过程中加入的约束太晚了为了使标签具有正确的初始高度。



我建议将单元格的标签安装(对于任何大小的类别),因为单元格的约束不会改变,取决于特征。



(当tableView约束确实改变时,单元格的约束不应该是有条件的,如果一个单元格,总是有相同的约束,不管大小类。)


I have been trying to get this tutorial dynamic-cell-height to work in ios8 for days now and can't figure out what is going on. It works in ios7 on the iphone and it works in both ios7 & ios8 on the iPAD but it doesn't work on any the iphone on ios8.

I think the problem lies in how and when the labels are being created within the cell.

I have the following code in the controller:

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.

    self.dbManager = [[DBManager alloc] initWithDatabaseFilename:@"tomhaisdb.sql"];

    [self loadData];

}

-(void)viewWillAppear:(BOOL)animated{
    [super viewWillAppear:animated];
    [self deselectAllRows];
}

-(void)deselectAllRows{
    for (NSIndexPath * indexPath in [self.tableView indexPathsForSelectedRows]) {
        [self.tableView deselectRowAtIndexPath:indexPath animated:NO];
    }
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

-(void)loadData {
    NSString *query = @"select * from favourites";

    if (self.favourites != nil) {
        self.favourites = nil;
    }

    self.favourites = [[NSArray alloc] initWithArray:[self.dbManager loadDataFromDB:query]];

   /* [self reloadDataWithCompletions:^{
         self.tableView.backgroundColor = [UIColor colorWithRed:28.0f/255.0f green:30.0f/255.0f blue:35.0f/255.0f alpha:1];
    }];*/
    [self reloadTableViewContent];
}

- (void)reloadTableViewContent {
    dispatch_async(dispatch_get_main_queue(), ^{
        [self.tableView reloadData];
        [self.tableView scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:NO];
    });
}

/*-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
    return 1;
}*/

#pragma mark - UITableViewDataSource

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    NSLog(@"Number of rows: %d", self.favourites.count);
    return self.favourites.count;
}


-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    return [self basicCellAtIndexPath:indexPath];
}

-(favouritedCell *)basicCellAtIndexPath:(NSIndexPath *)indexPath {
    favouritedCell *cell = [self.tableView dequeueReusableCellWithIdentifier:@"favouriteCell" forIndexPath:indexPath];
    [self configureBasicCell:cell atIndexPath:indexPath];
    return cell;
}

-(void)configureBasicCell:(favouritedCell *)cell atIndexPath:(NSIndexPath *)indexPath{
    NSInteger indexOfTomhaisText = [self.dbManager.arrColumnNames indexOfObject:@"tomhaisText"];
    NSString *tomhaisText = [[self.favourites objectAtIndex:indexPath.row] objectAtIndex:indexOfTomhaisText];
    [self setTomhaisForCell:cell item:tomhaisText];
    [self setAnswerForCell:cell item:tomhaisText]; // change this later
}

-(void)setTomhaisForCell:(favouritedCell *)cell item:(NSString *)item{
    [cell.favouriteText setText:item];
}

-(void)setAnswerForCell:(favouritedCell *)cell item:(NSString *)item{
    [cell.answer setText:item];
}

#pragma mark - UITableViewDelegate

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
   /* if ([[[UIDevice currentDevice]systemVersion]floatValue] >= 8.0) {
        return UITableViewAutomaticDimension;
    }
    else{*/
        return [self heightForFavouriteCellAtIndexPath:indexPath];
    /*}*/

}

-(CGFloat)heightForFavouriteCellAtIndexPath:(NSIndexPath *)indexPath{
    static favouritedCell *sizingCell = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sizingCell = [self.tableView dequeueReusableCellWithIdentifier:@"favouriteCell"];
    });

    [self configureBasicCell:sizingCell atIndexPath:indexPath];
    return [self calculateHeightForConfiguredSizingCell:sizingCell];
}

-(CGFloat)calculateHeightForConfiguredSizingCell:(UITableViewCell *)sizingCell{
    sizingCell.bounds = CGRectMake(0.0f, 0.0f, CGRectGetWidth(self.tableView.frame), CGRectGetHeight(sizingCell.bounds));
    NSLog(@"Bounds before Layout %@", NSStringFromCGRect(sizingCell.bounds));
     NSLog(@"Content View before Layout %@", NSStringFromCGRect(sizingCell.contentView.bounds));
    [sizingCell setNeedsLayout];
    [sizingCell layoutIfNeeded];

    CGSize size = [sizingCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];
    NSLog(@"Bounds after layout %@", NSStringFromCGRect(sizingCell.bounds));
    NSLog(@"Content View before Layout %@", NSStringFromCGRect(sizingCell.contentView.bounds));
    return size.height + 1.0f;
}

-(CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath{
    return 155.0f;
}

And in a custom Label the cell uses I have the following:

    @implementation favouriteLabel

- (void)setBounds:(CGRect)bounds {
    [super setBounds:bounds];

    // If this is a multiline label, need to make sure
    // preferredMaxLayoutWidth always matches the frame width
    // (i.e. orientation change can mess this up)

    if (self.numberOfLines == 0 && bounds.size.width != self.preferredMaxLayoutWidth) {
        self.preferredMaxLayoutWidth = self.bounds.size.width;
        NSLog(@"Label Bounds before update constraints %@", NSStringFromCGRect(self.bounds));
        [self setNeedsUpdateConstraints];
        NSLog(@"Label Bounds after update constraints %@", NSStringFromCGRect(self.bounds));
    }
}

@end

The reason I think my problem lies with when the labels get created is because in ios 7 I get output like this:

2015-06-01 20:07:10.563 Facts[63322:607] Label Bounds before update constraints {{0, 0}, {216, 2}}
2015-06-01 20:07:10.563 Facts[63322:607] Label Bounds after update constraints {{0, 0}, {216, 2}}
2015-06-01 20:07:10.563 Facts[63322:607] Label Bounds before update constraints {{0, 0}, {217, 40}}
2015-06-01 20:07:10.563 Facts[63322:607] Label Bounds after update constraints {{0, 0}, {217, 40}}
>2015-06-01 20:07:10.564 Facts[63322:607] Bounds after layout {{0, 0}, {256, 82}}
2015-06-01 20:07:10.564 Facts[63322:607] Content View before Layout {{0, 0}, {256, 82}}
2015-06-01 20:07:10.564 Facts[63322:607] Bounds before Layout {{0, 0}, {256, 82}}
2015-06-01 20:07:10.564 Facts[63322:607] Content View before Layout {{0, 0}, {256, 82}}
2015-06-01 20:07:10.565 Facts[63322:607] Bounds after layout {{0, 0}, {256, 82}}
2015-06-01 20:07:10.565 Facts[63322:607] Content View before Layout {{0, 0}, {256, 82}}
2015-06-01 20:07:10.569 Facts[63322:607] Label Bounds before update constraints {{0, 0}, {216, 74.5}}
2015-06-01 20:07:10.569 Facts[63322:607] Label Bounds after update constraints {{0, 0}, {216, 74.5}}
2015-06-01 20:07:10.569 Facts[63322:607] Label Bounds before update constraints {{0, 0}, {217, 40}}
2015-06-01 20:07:10.570 Facts[63322:607] Label Bounds after update constraints {{0, 0}, {217, 40}}

But in ios8 the output is different.

2015-06-01 20:18:06.049 Facts[63396:81689795] Bounds before Layout {{0, 0}, {256, 44}}
2015-06-01 20:18:06.049 Facts[63396:81689795] Content View before Layout {{0, 0}, {320, 44}}
2015-06-01 20:18:06.131 Facts[63396:81689795] Label Bounds before update constraints {{0, 0}, {216, 0}}
2015-06-01 20:18:06.131 Facts[63396:81689795] Label Bounds after update constraints {{0, 0}, {216, 0}}
2015-06-01 20:18:06.131 Facts[63396:81689795] Label Bounds before update constraints {{0, 0}, {217, 4.5}}
2015-06-01 20:18:06.131 Facts[63396:81689795] Label Bounds after update constraints {{0, 0}, {217, 4.5}}

In ios7 the label seems to be created first, then cell bounds, and then the label is resized again. But in ios8 we see the content view output first and only then do we see the output for the label.

I'm sorry I can't explain it any better. It's a bit of a mystery to me how ios makes it's tables so I'm really stuck as to why it works in ios7 and not in ios8

Any help most appreciated. I had already written this question up here: Dynamic Cell Height autolayout IOS But I think I threw in a red herring about autolayout on that question.

解决方案

The frame was misplaced for the Answer label. Since the label was not installed for anyXany, the warning wasn't visible in Interface Builder.

Because the constraints didn't equal the expected height, that stopped Auto Layout from properly solving the cell height for iOS 8.

Quick fix is to tick its Installed box for anyXany. You'll see the warning show up. Select the Answer label, select Editor->AutoLayout Issues->Update Frames, and you're good to go!

Update:

The reason why the labels show up initially, without needing to reload, is because the anyXany box is ticked. Apple sees there are constraints installed, and the initial height is correct without reload or scrolling.

When the box is not ticked, the constraints get added too late in the layout process for the label to have the right initial height.

I'd recommend leaving the cell's labels installed (for any size class), since the cell's constraints don't change, depending on traits.

(While the tableView constraints do change, the cell's constraints should not be conditional. If there is a cell, it will always have the same constraints, regardless of size class.)

这篇关于使用AutoLayout的UITableView中的动态单元格高度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆