UITableViewCell自动布局

4
我在自动布局方面遇到了问题。我有一个UITableViewCell和一个内部的视图。我希望这个视图比单元格小,因此我添加了以下约束:
  • 垂直间距(10)顶部
  • 垂直间距(10)底部
  • 水平间距(10)前导空间
  • 水平间距(10)尾随空间
当tableView出现时,单元格显示良好,但是如果我向下滚动tableView并向上滚动,则单元格中的视图将被重新调整大小,并且现在占用了单元格的全部空间。
正确的单元格: enter image description here 不正确的单元格(滚动后) enter image description here 我已经搜索过了,但没有找到类似的结果。我认为这个人有同样的问题,但是没有答案:类似问题 感谢您的任何帮助!

请在此处添加相关代码 :) - iPatel
你是从nib或storyboard中加载单元格,还是完全在代码中创建它?你是否使用了UITableViewCell的自定义子类? - rob mayoff
@robmayoff 我正在使用一个 xib 来创建这个单元格,并从 xib 中加载它。我还为此使用了 UITableViewCell 的自定义子类。 - Lukas
3个回答

3

我终于在这里找到了我的问题的答案。在我的自定义UITableViewCell类中,我做了以下操作:

- (void)awakeFromNib
{
    [super awakeFromNib];

    for (NSLayoutConstraint *cellConstraint in self.constraints)
    {
        [self removeConstraint:cellConstraint];

        id firstItem = cellConstraint.firstItem == self ? self.contentView : cellConstraint.firstItem;
        id seccondItem = cellConstraint.secondItem == self ? self.contentView : cellConstraint.secondItem;

        NSLayoutConstraint* contentViewConstraint = [NSLayoutConstraint constraintWithItem:firstItem
                                                                                 attribute:cellConstraint.firstAttribute
                                                                                 relatedBy:cellConstraint.relation
                                                                                    toItem:seccondItem
                                                                                 attribute:cellConstraint.secondAttribute
                                                                                multiplier:cellConstraint.multiplier
                                                                                  constant:cellConstraint.constant];

        [self.contentView addConstraint:contentViewConstraint];
    }
}

我猜测内容视图调整其内容大小或类似的操作。如果有更简单的解释和更简单的方法,我仍在等待其他答案。非常感谢您的帮助!

1
在xib(或故事板)中创建的UITableViewCell上的约束直接连接到单元格本身,而不是其contentView子视图。 但是它们需要连接到contentView以进行正确的布局。 这就是为什么你的修复有效。 我不知道这是Xcode中的错误还是UIKit中的错误。 - rob mayoff
@robmayoff - 我认为这是一个 IB/XCode 的 bug,而不是 UIKit 的问题。如果您检查 XCode 4.6 发出的 storyboard XML,就会清楚地看到,对于 contentView 的子视图,约束被添加到了 cell 而不是 contentView 上。在比 4.6 更高版本的 XCode 中,已经纠正了这个问题,现在约束属于 contentView。 - TomSwift

1
今天我在使用Xcode 5和storyboards时遇到了同样的问题。最初,我的自定义表格视图单元格会正确显示,但是当我滚动表格视图并且单元格被重用时,布局会混乱。解决方法是像这样调用setNeedsLayout:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    SettingTableViewCell *tableViewCell = [tableView dequeueReusableCellWithIdentifier:@"Setting" forIndexPath:indexPath];

    [tableViewCell.contentView setNeedsLayout];

    return tableViewCell;
}


真正的问题:

我将我的标签输出命名为textLabel,这与UITableViewCell内置的标签属性名称相同。这导致了各种奇怪的问题。一旦我将输出属性名称更改为唯一名称,我的布局问题就得到了解决。


我发现所有的单元格都应该有一个内部视图,将这个视图连接作为单元格的内容视图,然后再添加内容,比如uilabels和其他东西。这种方式似乎可以摆脱所有问题。 - Lukas
我也遇到了“imageView”的同样问题。非常感谢。 - Torsten B

0
这个问题是由于您的UITableView重用单元格而不是创建新单元格所导致的。 我给你一些建议,可能对你有帮助。
1)在中间添加UIView
 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath   
  {
    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil)
    {
        /// Your code;
    }
 return cell;

}

1) 将您的UIView添加到cell.contentView。

编辑:

在您按照我的编辑答案之前,我想告诉您,以下代码对于内存管理不好,因为它将为UITableView的每一行创建一个新单元格,请小心使用。

但是,如果UITableView有限制的行数(约50-100个),则最好使用以下代码,如果适合您。

NSString *CellIdentifier = [NSString stringWithFormat:@"S%1dR%1d",indexPath.section,indexPath.row];
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if(cell == nil)
    {
    } 

谢谢,但那并不起作用。我真的不明白为什么会发生这种情况,这在简单的UIview中并没有发生,只在tableviewcell中发生。也许我需要设置[view setNeedsLayout]或类似的东西,使自动布局约束在tableview cell中起作用? - Lukas
谢谢你的帮助,但那样做会非常缓慢和低效。我想用正确的方法来做 :) - Lukas
这是在UITableView中严重滥用单元格重用模式,一定要避免,因为它会导致更大的内存使用。 - patr1ck

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接