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

时间:2014-10-05 01:31:26

标签: ios objective-c uitableview autolayout

我正在使用 AutoLayout ,并且出于某种原因,只要表格视图加载:

  • 屏幕上的第一对表格视图单元格未布局 正确地
  • 但滚动到的表格视图格式 布局 正确地
  • 但是当我向后滚动到原始表格视图中没有铺设的单元格时 正确地,一旦他们离开屏幕,然后在屏幕上突然显示所有 正确布局

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

的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代码中来手动设置它。为任何比正常估计的单元格大的单元手动设置它(即如果它有任何图像)。

3 个答案:

答案 0 :(得分:4)

看来,自我调整UITableView单元格仍存在一些缺陷。

以下是我们正在使用的解决方法。 我不知道确切的潜在机制,但这是我们发现的最简单的黑客攻击。

@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;
}

BTW,在您的代码中,这是一个问题。

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

您不应在View中创建/ addSubview tableView:cellForRowAtIndexPath:。您的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"]];

答案 1 :(得分: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错误。

使用我提到的代码,当单元格“行高”未设置为自定义时,它似乎不起作用。通过选择单元格并单击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改变了苹果!

对于preferredMaxLayoutWidth的IB设置似乎存在问题,因为iOS 7无法使用自动功能,如果您在多个设备上使用相同的UILabel,它只能使用1宽度。所以iOS 8平板电脑上的UITableViewCell会更大,因为相同的手机需要在iOS 8 iPhone上拥有2条线。

答案 2 :(得分:1)

我相信如果您要将子视图添加到UITableViewCell并使用AutoLayout,则会因自动调整大小而产生不需要的结果。尝试在UITableViewCell的子视图上调用setTranslatesAutoresizingMaskINtoConstraints: NO