表视图单元格仅在屏幕外时自动布局

Posted

技术标签:

【中文标题】表视图单元格仅在屏幕外时自动布局【英文标题】:Table View Cells only AutoLayout when offscreen 【发布时间】:2014-10-05 01:31:25 【问题描述】:

我正在使用 AutoLayout,并且由于某种原因,一旦 Table View 加载:

屏幕上的第一对表格视图单元格没有布局 正确 但是表格视图单元格在屏幕外滚动到时被布局 正确 但是当我向上滚动到未放置的原始表格视图单元格时 正确输出, 一旦他们离开屏幕然后又回到屏幕上所有突然 布局正确

任何帮助将不胜感激,谢谢!

cellForRowAtIndexPath:

if ([model isKindOfClass:[FRSS self]]) 
        FRSS *fDan = (FRSS *)model;
        // configure cell
        MRWebListTableViewCell  *api1Cell = [tableView dequeueReusableCellWithIdentifier:@"YourAPI1Cell"];

        // RSS
        NSString *title = [NSString stringWithFormat:@"%@", fDan.title];

        // Get string from XML
        NSString *dateString = [self timeSincePublished:fDan.pubDate];

        // Get description without tags
        NSString *description = [self removehtmlTags:fDan.description];

        NSString *link = [NSString stringWithFormat:@"%@", fDan.link];

        api1Cell.labelHeadline.text = title;
        api1Cell.labelDescription.text = description;
        api1Cell.labelPublished.text = dateString;

        // Top Image View
        UIImageView *imv = [[UIImageView alloc]initWithFrame:CGRectMake(15, 20, 50, 50)];
        imv.image=[UIImage imageNamed:@"e_r.png"];
        [api1Cell.contentView addSubview:imv];

        return api1Cell;

更新:即使在尝试了很多不同的事情之后,AutoLayout 仍然存在很多问题。

这与heightForRowAtIndexPath 有很大关系。最终需要通过将函数添加到 ViewController 代码中来手动设置它。为任何比正常估计单元格大得多的单元格手动设置它(即,如果其中有任何图像)。

【问题讨论】:

发现另一个问题并更新了我的答案 【参考方案1】:

看来,self-sizing UITableView 单元格还是有一些缺陷的。

这是我们正在使用的解决方法。 虽然我不知道确切的底层机制,但这是我们发现的最简单的 hack。

@implemetation YourTableViewCell

- (void)setFrame:(CGRect)frame 
    if(frame.size.width != self.bounds.size.width) 
        [super setFrame:frame];
        self.contentView.bounds = CGRectMake(0, 0, frame.size.width, frame.size.height);
        [self.contentView layoutIfNeeded];
    
    else 
        [super setFrame:frame];
    


// .. any other methods

@end

如果您无法编辑 UITableViewCell 子类,请在您的 UITableViewDataSource 中尝试此操作:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"CellIdentifier" forIndexPath:indexPath];

    // setup cell ...

    CGSize sysSize = [cell.contentView systemLayoutSizeFittingSize:CGSizeMake(tableView.bounds.size.width, CGFLOAT_MAX)];
    cell.contentView.bounds = CGRectMake(0,0, sysSize.width, sysSize.height);
    [cell.contentView layoutIfNeeded];
    return cell;


顺便说一句,在您的代码中,这是一个问题。

    // Top Image View
    UIImageView *imv = [[UIImageView alloc]initWithFrame:CGRectMake(15, 20, 50, 50)];
    imv.image=[UIImage imageNamed:@"e_r.png"];
    [api1Cell.contentView addSubview:imv];

您不应在tableView:cellForRowAtIndexPath: 中创建/添加子视图View。您的 NIB 中已经有 UIImageView 了,对吧?像这样使用它:

api1Cell.topImageView.image = [UIImage imageNamed:@"e_r.png"];

如果您的图像是动态的,最简单的解决方案是使用像 SDWebImage 这样的库

#import <SDWebImage/UIImageView+WebCache.h>

...

    if ([model isKindOfClass:[FRSS self]]) 
        FRSS *fDan = (FRSS *)model;
        // configure cell
        MRWebListTableViewCell  *api1Cell = [tableView dequeueReusableCellWithIdentifier:@"YourAPI1Cell"];

        ...

        // Top Image View
        // for example: fDan.imageURL is a image URL string
        [api1Cell.topImageView sd_setImageWithURL:[NSURLURLWithString: fDan.imageURL]
                                 placeholderImage:[UIImage imageNamed: @"e_r.png"]];

【讨论】:

谢谢!我会尝试在我的代码中得到这个,也感谢关于图像视图的提示! 另外,我的图像视图不是静态图像,它是从 API 返回的任何图像。你的建议仍然适用吗?【参考方案2】:

ios 8 的自动单元格高度似乎不太好用。我在 iOS 6 / 7 中遇到了类似的问题,在我更新到 iOS 8 后它仍然有效。所以也许你应该暂时去老学校。

这里有一些我的代码示例:AutoLayout multiline UILabel cutting off some text

在这里:AutoLayout uitableviewcell in landscape and on iPad calculating height based on portrait iPhone

长话短说,iOS 8 之前的方式涉及保留一个单元格的副本,仅用于计算 tableView:heightForRowAtIndexPath: 内的高度。但这对于处理多行 UILabel 是不够的。每次调用 layoutSubviews 时,我都必须继承 UILabel 以更新 preferredMaxLayoutWidth。

preferredMaxLayoutWidth “修复”似乎是我错过的神奇秘密。一旦我这样做了,我的大部分细胞都可以正常工作。

第二个问题我只需要我正确设置内容压缩阻力和内容拥抱属性,因此例如告诉标签拥抱文本将意味着它不会扩展以填充空白,这将导致单元格收缩。

完成这两件事后,我的单元格现在可以处理任何字体大小或任何数量的文本,而无需任何凌乱的布局代码。这需要学习很多东西,但我确实认为它最终得到了回报,因为我的应用中有很多动态内容。

编辑

在遇到我自己在 iOS 8 上的一些问题后,我添加了更多细节来解决这些非常奇怪的 autoLayout 错误。

使用我提到的代码,当单元格“行高”未设置为自定义时,它似乎不起作用。通过选择单元格并单击自动布局选项卡(所有内容压缩阻力设置等都在其中),可以在 IB 中找到此设置。按下复选框,它将填充一个临时高度。

其次,在我的代码中,我保留了一个单元格的本地副本,然后在 heightForRowAtIndexPath: 方法中多次重复使用它。每次调用时,这似乎都会使单元格高度增加很多。我不得不通过调用重新初始化本地副本:

localCopy = [self.tableView dequeueReusableCellWithIdentifier:@"mycell"];

似乎新的 Xcode 6 / iOS 8 更改非常不向后兼容 iOS 7,而且管理方式似乎完全不同。

希望这会有所帮助。

编辑 2

看完这个问题:iOS AutoLayout multi-line UILabel

我遇到了 iOS 7 / iOS 8 自动布局支持的另一个问题!!!我正在为 iOS 8 覆盖 layoutSubviews 我还需要覆盖 setBounds 以在调用 super 后更新 preferredMaxLayoutWidth。 WTF 变苹果了!

似乎是IB中preferredMaxLayoutWidth的设置有问题,因为iOS 7不能使用自动功能,如果你在多个设备上使用相同的UILabel,它只会使用1宽度。因此,iOS 8 平板电脑上的UITableViewCell 会更大,因为在 iOS 8 iPhone 上,同一个单元格需要有 2 行。

【讨论】:

谢谢,我要试试这个! 我只是在寻找 iOS8 支持,这是否会减少您的一些答案?再次感谢西蒙! @Reez 我不确定仅针对 8 个目标是否会有所改善。我没有测试它,因为我不能为我当前的应用程序这样做。我不知道的是我第一次记录了一个针对苹果的错误,并且从那以后我发现了桶负载的问题。我昨天放弃了,将我的基础 SDK 设置为 7,它似乎解决了我所有的 autoLayout 问题。我在 8 中发现了另一个问题,对于一个有 7 个标签的单元格,它会出现其中 2 个被压扁,6 秒后它会在 3 上再次随机调用 setBounds 并更新单元格。我没有运行代码,也没有触摸单元格。它只是无缘无故地发生 @Reez 我已经在开发者论坛上发起了一个帖子,至少有一个评论说他们发现 8 太不稳定了。下周我将尝试看看我能否在 Xcode 6 中定位 7 并针对 iPhone 6 / 6+ 优化该应用程序。如果可以的话,我会放弃 8 个支持,直到苹果修复这些东西 很棒的西蒙,感谢您提供有关这方面的信息。如果 8 这么不稳定,那就有点疯狂了。【参考方案3】:

我相信,如果您将子视图添加到 UITableViewCell 并使用 AutoLayout,由于自动调整大小,您会得到不想要的结果。尝试在 UITableViewCell 的子视图上调用 setTranslatesAutoresizingMaskINtoConstraints: NO

【讨论】:

这仅适用于 iOS8 吗?希望是,因为我肯定只需要支持iOS8。谢谢!!

以上是关于表视图单元格仅在屏幕外时自动布局的主要内容,如果未能解决你的问题,请参考以下文章

按钮之间的自动布局边距仅在 4" 屏幕上不正确

根据各种屏幕尺寸自动布局集合视图

集合视图单元格的自动布局行为怪异

使用堆栈视图和自动布局创建自定义 UITableViewCell

如何使用自动布局来调整表格视图单元格中的视图大小?

表格视图单元格中的 ImageView 切断标签(自动布局)[关闭]