contentView没有在iOS 6 UITableViewCell原型单元格中缩进

Sko*_*ota 39 uitableview ios ios6

我正在UITableViewCell使用Storyboard中的原型单元配置自定义.但是,所有UILabels(和其他UI元素)似乎都没有添加到单元格中contentView,而是UITableViewCell直接添加到视图中.当单元格进入编辑模式时,这会产生问题,因为内容不会自动移位/缩进(如果它们位于内部,它会执行此操作contentView).

有没有办法contentView在使用Interface Builder/Storyboard/prototype cell布局单元格时添加UI元素?我找到的唯一方法是在代码中创建所有内容并使用[cell.contentView addSubView:labelOne]不太好的内容,因为以图形方式布置单元格要容易得多.

Sko*_*ota 66

在进一步调查(查看单元格的子视图层次结构)时,Interface Builder会将子视图放在单元格中contentView,它看起来不像它.

问题的根本原因是iOS 6自动布局.当单元格被置于编辑模式(并缩进)时,contentView它也会缩进,因此可以理解所有子视图中的所有子视图contentView都会因为在其中而移动(缩进)contentView.但是,Interface Builder应用的所有自动布局约束似乎都与UITableViewCell自身相关,而不是相对于contentView.这意味着即使contentView缩进,其中包含的子视图也不会 - 约束条件负责.

例如,当我将a UILabel放入单元格(并且将其定位在距单元格的左侧10个点)时,IB自动应用约束"水平空间(10)".但是,这个约束是相对于UITableViewCellNOT的contentView.这意味着当单元格缩进和contentView移动时,标签保持不变,因为它符合约束条件,从而保持距离左侧10个点UITableViewCell.

不幸的是(据我所知),没有办法从IB本身中删除这些IB创建的约束,所以这就是我如何解决问题.

UITableViewCell单元格的子类中,我IBOutlet为该约束创建了一个名为cellLabelHSpaceConstraint.你还需要一个IBOutlet标签本身,我打电话给你cellLabel.然后,我-awakeFromNib按照以下方式实现了该方法:

- (void)awakeFromNib {

    // -------------------------------------------------------------------
    // We need to create our own constraint which is effective against the
    // contentView, so the UI elements indent when the cell is put into
    // editing mode
    // -------------------------------------------------------------------

    // Remove the IB added horizontal constraint, as that's effective
    // against the cell not the contentView
    [self removeConstraint:self.cellLabelHSpaceConstraint];

    // Create a dictionary to represent the view being positioned
    NSDictionary *labelViewDictionary = NSDictionaryOfVariableBindings(_cellLabel);   

    // Create the new constraint
    NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"|-10-[_cellLabel]" options:0 metrics:nil views:labelViewDictionary];

    // Add the constraint against the contentView
    [self.contentView addConstraints:constraints];

}
Run Code Online (Sandbox Code Playgroud)

总之,上面将删除IB自动添加的水平间距约束(因为对比UITableViewCell而不是contentView),然后我们定义并添加我们自己的约束contentView.

在我的情况下,UILabels单元格中的所有其他单元都是根据位置定位的,cellLabel所以当我修复了这个元素的约束/定位时,所有其他元素都跟着并正确定位.但是,如果您的布局更复杂,那么您可能还需要为其他子视图执行此操作.

  • 您可以通过在界面构建器中关闭自动布局来解决此问题,无论是整个故事板还是仅包含您的单元格的笔尖.请参阅回答查看详情:http://stackoverflow.com/questions/12833176/indentation-not-working-on-custom-uitableviewcell (3认同)
  • +1非常有趣的发现和解决方法! (2认同)

Adr*_*ian 32

如前所述,XCode的Interface Builder隐藏了UITableViewCell的contentView.实际上,添加到UITableViewCell的所有UI元素实际上都是contentView的子视图.

目前,它没有为布局约束做同样的魔术,这意味着它们都在UITableViewCell级别表达.

解决方法是在子类的awakeFromNib中将所有NSAutoLayoutConstrains从UITableViewCell移动到它的contentView并根据contentView表达它们:

-(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];
  }
}
Run Code Online (Sandbox Code Playgroud)


小智 9

这是一个子类,基于其他答案的想法,我将基于我的自定义单元格:

@interface FixedTableViewCell ()

- (void)initFixedTableViewCell;

@end

@interface FixedTableViewCell : UITableViewCell

@end

@implementation FixedTableViewCell

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
    if (nil != (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier])) {
        [self initFixedTableViewCell];
    }
    return self;
}

- (void)awakeFromNib {
    [super awakeFromNib];

    [self initFixedTableViewCell];
}

- (void)initFixedTableViewCell {
    for (NSInteger i = self.constraints.count - 1; i >= 0; i--) {
        NSLayoutConstraint *constraint = [self.constraints objectAtIndex:i];

        id firstItem = constraint.firstItem;
        id secondItem = constraint.secondItem;

        BOOL shouldMoveToContentView = YES;

        if ([firstItem isDescendantOfView:self.contentView]) {
            if (NO == [secondItem isDescendantOfView:self.contentView]) {
                secondItem = self.contentView;
            }
        }
        else if ([secondItem isDescendantOfView:self.contentView]) {
            if (NO == [firstItem isDescendantOfView:self.contentView]) {
                firstItem = self.contentView;
            }
        }
        else {
            shouldMoveToContentView = NO;
        }

        if (shouldMoveToContentView) {
            [self removeConstraint:constraint];
            NSLayoutConstraint *contentViewConstraint = [NSLayoutConstraint constraintWithItem:firstItem
                                                                                     attribute:constraint.firstAttribute
                                                                                     relatedBy:constraint.relation
                                                                                        toItem:secondItem
                                                                                     attribute:constraint.secondAttribute
                                                                                    multiplier:constraint.multiplier
                                                                                      constant:constraint.constant];
            [self.contentView addConstraint:contentViewConstraint];
        }
    }
}

@end
Run Code Online (Sandbox Code Playgroud)

  • 这对我很有用,但你也需要保留约束优先级:"contentViewConstraint.priority = constraint.priority" (2认同)

rai*_*ade 6

子类化的替代方法是修改cellForRowAtIndexPath中的约束.

将单元格的所有内容嵌入容器视图中.然后将前导和尾随约束指向cell.contentView而不是表视图单元格.

  UIView *containerView = [cell viewWithTag:999];
  UIView *contentView = [cell contentView];

  //remove existing leading and trailing constraints
  for(NSLayoutConstraint *c in [cell constraints]){
    if(c.firstItem==containerView && (c.firstAttribute==NSLayoutAttributeLeading || c.firstAttribute==NSLayoutAttributeTrailing)){
      [cell removeConstraint:c];
    }
  }

  NSLayoutConstraint *trailing = [NSLayoutConstraint
                                 constraintWithItem:containerView
                                 attribute:NSLayoutAttributeTrailing
                                 relatedBy:NSLayoutRelationEqual
                                 toItem:contentView
                                 attribute:NSLayoutAttributeTrailing
                                 multiplier:1
                                 constant:0];

  NSLayoutConstraint *leading = [NSLayoutConstraint
                                 constraintWithItem:containerView
                                 attribute:NSLayoutAttributeLeading
                                 relatedBy:NSLayoutRelationEqual
                                 toItem:contentView
                                 attribute:NSLayoutAttributeLeading
                                 multiplier:1
                                 constant:0];

  [cell addConstraint:trailing];
  [cell addConstraint:leading];
Run Code Online (Sandbox Code Playgroud)