indentationLevelForRowAtIndexPath不缩进自定义单元格

时间:2010-03-23 19:02:40

标签: iphone uitableview

我已覆盖tableView:indentationLevelForRowAtIndexPath派生类中的UITableViewController方法,如下所示:

- (NSInteger)tableView:(UITableView *)tableView indentationLevelForRowAtIndexPath:(NSIndexPath *)indexPath {
    NSDictionary* item = [self.projects objectAtIndex:indexPath.row];
    int indentationLevel = [[item objectForKey:@"indent"] intValue];
    DLog (@"Indentation Level for Row %d : %d", indexPath.row, indentationLevel);
    return indentationLevel;
}

我最初认为这不是被调用但是操作员错误(错误,我的)并且我没有定义符号DEBUG = 1.

然而,它被称为(对我!),这是日志输出:

 -[RootViewController tableView:indentationLevelForRowAtIndexPath:] [Line 129] Indentation Level for Row 0 : 1
 -[RootViewController tableView:indentationLevelForRowAtIndexPath:] [Line 129] Indentation Level for Row 1 : 1
 -[RootViewController tableView:indentationLevelForRowAtIndexPath:] [Line 129] Indentation Level for Row 2 : 2
 -[RootViewController tableView:indentationLevelForRowAtIndexPath:] [Line 129] Indentation Level for Row 3 : 2
 -[RootViewController tableView:indentationLevelForRowAtIndexPath:] [Line 129] Indentation Level for Row 4 : 2
 -[RootViewController tableView:indentationLevelForRowAtIndexPath:] [Line 129] Indentation Level for Row 5 : 1
 -[RootViewController tableView:indentationLevelForRowAtIndexPath:] [Line 129] Indentation Level for Row 6 : 2
 -[RootViewController tableView:indentationLevelForRowAtIndexPath:] [Line 129] Indentation Level for Row 7 : 2
 -[RootViewController tableView:indentationLevelForRowAtIndexPath:] [Line 129] Indentation Level for Row 8 : 1

但是,这并不影响细胞的布局。没有缩进。

这是我的itemCellForRowAtIndexPath实施,如果这有任何区别:

-(UITableViewCell*)tableView:(UITableView *)tableView itemCellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString* cellIdentifier = @"projectItemCell";
    ProjectItemTableViewCell* cell = (ProjectItemTableViewCell*)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];

    if (cell == nil) {
        NSArray* nib = [[NSBundle mainBundle] loadNibNamed:@"ProjectItemTableViewCell" owner:self options:nil];
        for (id oneObject in nib) {
            if ([oneObject isKindOfClass:[ProjectItemTableViewCell class]]) {
                cell = (ProjectItemTableViewCell*)oneObject;
            }
        }
    }

    NSDictionary* item = [self.projects objectAtIndex:indexPath.row];
    cell.projectDescLabel.text = [item objectForKey:@"name"];
    cell.itemCountlabel.text = [NSString stringWithFormat:@"%d", [[item objectForKey:@"cache_count"] intValue]];
    cell.itemCountlabel.backgroundColor = [UIColor colorForHex:[item objectForKey:@"color"]];
    cell.indentationWidth = 20;
    return cell;
}

如何缩进我在Interface Builder中定义的自定义UITableViewCell

如果我使用下面的代码更改itemCellForRowAtIndexPath以使用默认UITableViewCell,那么它会缩进。

static NSString* cellIdentifier = @"projectItemCell";
UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier] autorelease];
}

NSDictionary* item = [self.projects objectAtIndex:indexPath.row];
cell.textLabel.text = [item objectForKey:@"name"];
cell.indentationWidth = 40;

return cell;

9 个答案:

答案 0 :(得分:45)

是的,似乎自定义表格单元格不会自动执行此操作?您需要覆盖表格单元格类中的layoutSubviews方法。有关如何执行此操作,请参阅this question

这段代码对我来说非常合适(虽然如果你设置一个自定义高度w /委托也要小心,它们似乎相互干扰):

- (void)layoutSubviews
{
    [super layoutSubviews];
    float indentPoints = self.indentationLevel * self.indentationWidth;

    self.contentView.frame = CGRectMake(
        indentPoints,
        self.contentView.frame.origin.y,
        self.contentView.frame.size.width - indentPoints, 
        self.contentView.frame.size.height
    );
}

编辑iOS8及更高版本

以上在iOS上对我有用,但在尝试自动调整单元格的高度时也会产生微妙的错误。有一个更简单的解决方案:如果您为单元格设置了autolayout,只需设置contentView的左边距:

override func layoutSubviews() {
    super.layoutSubviews()
    self.contentView.layoutMargins.left = CGFloat(self.indentationLevel) * self.indentationWidth
    self.contentView.layoutIfNeeded()
}

答案 1 :(得分:2)

如果使用带约束的自定义单元格,最方便的方法是设置一个约束,该约束将从左边缘移动所有内容,然后根据单元格子类中的缩进级别更新它。

假设已为单元格设置indentationWidth

override var indentationLevel: Int {
    didSet {
        self.leftConstraint.constant = CGFloat(self.indentationLevel) * self.indentationWidth
    }
}

答案 2 :(得分:1)

您是否已将ProjectItemTableViewCell的子视图添加到单元格的contentView中?此外,您需要设置子视图的自动调整大小的掩码,以便在contentView大小更改时重新定位它们。

答案 3 :(得分:1)

与接受的答案类似,这是在iOS 8中使用layoutSubviews代替AutoLayout的方式。

_viewConstraintsNSMutableArray ivar,_imageView为距离单元格内容视图左侧最近的视图。

- (void)layoutSubviews
{
    float indentPoints = indentationLevel * [self indentationWidth];

    [self removeConstraints:_viewConstraints];
    [_viewConstraints removeAllObjects];

    NSDictionary *views = NSDictionaryOfVariableBindings(imageView);
    [_viewConstraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:[NSString stringWithFormat:@"H:|-(%f@1000)-[_imageView]", indentPoints] options:0 metrics:nil views:views]];
    [self addConstraints:_viewConstraints];
}

如果你有AutoLayout约束来定义视图中的其他所有内容,那么这应该将整个视图推送到所需的缩进量。

请注意使用Nib: 您应该将约束(在这种情况下,在_imageView和它的超级视图之间)定义为>=一些数字(在我的例子中它是20)。然后原始约束,以及layoutSubviews中添加/删除的约束不会相互冲突。

您还应该考虑在awakeFromNib

中调用以下内容
[_imageView setTranslatesAutoresizingMaskIntoConstraints:NO]

这是旧的"弹簧和支柱"不要妨碍你添加的限制。

答案 4 :(得分:1)

在某些情况下,接受的答案可能会导致iOS8无限循环。因此,最好覆盖自定义setFrame的{​​{1}}并在那里调整框架。

UITableViewCell

答案 5 :(得分:0)

您是否意外地在自定义表格单元格类中覆盖了shouldIndentWhileEditing:NO

答案 6 :(得分:0)

缩进级别是UITableViewCell本身的属性。尝试在创建单元格时在单元格上设置它,并在tableView:indentationLevelForRowAtIndexPath:

中返回此值

答案 7 :(得分:0)

约束到界面构建器中自定义表格单元格的内容视图的前沿。对于一个简单的边际,这似乎就足够了。如果需要以编程方式更改缩进,请参阅Dean的答案。或https://stackoverflow.com/a/7321461/5000071

答案 8 :(得分:0)

我用这段代码来缩进我的tableView单元格。最初它运行良好,但后来这导致了一些问题(例如,在缩进时干扰我的UITextView动态高度更新,这是我的tableView单元格的子视图。不知何故,我的UITextView认为它的宽度仍然是原始contentView的宽度)。 / p>

float indentPoints = self.indentationLevel * self.indentationWidth;
self.contentView.frame = CGRectMake(
    indentPoints,
    self.contentView.frame.origin.y,
    self.contentView.frame.size.width - indentPoints, 
    self.contentView.frame.size.height
)

所以我不推荐上面的代码,而是使用自动布局方法作为Dean的答案,稍有不同(Swift版本):

override func awakeFromNib() {
    super.awakeFromNib()
    self.indentationWidth = 20.0
    self.indentationLevel = 0
}
override func layoutSubviews() {
    super.layoutSubviews()
    let margin: CGFloat = 20.0
    let indentPoints = CGFloat(self.indentationLevel) * self.indentationWidth
    indentConstraint.constant = margin + indentPoints
}

“indentConstraint”是一个IBOutlet(使用contentView的主要约束),代码是在自定义的tableViewCell子类中编写的,它工作得很好,而且你不需要删除或添加任何约束,这样更昂贵。我认为自动布局方法是缩进tableView单元格的更好方法。