【问题标题】:indentationLevelForRowAtIndexPath not indenting custom cellindentationLevelForRowAtIndexPath 不缩进自定义单元格
【发布时间】:2011-01-30 23:06:40
【问题描述】:

我在我的UITableViewController 派生类中重写了tableView:indentationLevelForRowAtIndexPath 方法,如下所示:

- (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;

【问题讨论】:

    标签: iphone uitableview


    【解决方案1】:

    您是否在自定义表格单元格类中不小心将shouldIndentWhileEditing: 覆盖为NO

    【讨论】:

    • 在 Interface Builder 中检查编辑时缩进
    • 我还添加了行'cell.shouldIndentWhileEditing = YES;'到 cellForRowAtIndexPath 方法。所以看起来不会。
    【解决方案2】:

    缩进级别是UITableViewCell 本身的属性。尝试在创建时将其设置在单元格上,并在tableView:indentationLevelForRowAtIndexPath:中返回此值

    【讨论】:

    • 我添加了以下行:cell.indentationLevel = [[item objectForKey:@"indent"] intValue]; cell.indentationWidth = 20;到细胞创建。也不行。
    【解决方案3】:

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

    【讨论】:

    • 我在 xib 中添加了一个 UITableViewCell,在 UITableViewCell 中添加了一个视图,在视图中添加了 2 个 UILabel。
    【解决方案4】:

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

    这段代码对我来说非常有效(尽管如果你也设置了一个自定义高度和委托,请小心,它们似乎会相互干扰):

    - (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 上对我有用,但是在尝试自动调整单元格的高度时也会导致一些细微的错误。有一个更简单的解决方案:如果您为单元格打开了自动布局,只需设置 contentView 的左边距:

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

    【讨论】:

    • 在 ios9 和 ios8 中测试过,我可以确认它可以工作。也许你应该检查你的约束
    • 这可能会导致 iOS8 无限循环;这将调用 layoutSubview 来一次又一次地调用。我通过创建一个前导约束来修复它,并根据 indentationLevel 更新 updateConstraint 函数中的常量
    • 不错的解决方案!对于那些不想依赖布局边距并在单元格子类中使用自动布局的人,请尝试这种方法 - stackoverflow.com/a/47946688/3160561
    • 我发现我需要将 layoutMargins.left 偏移它的当前值 - 我已经更新了解决方案。
    【解决方案5】:

    与已接受的答案类似,这就是在 iOS 8 中如何做到这一点,同时仍然使用 layoutSubviews 和 AutoLayout。

    _viewConstraints 作为 NSMutableArray 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 约束,那么这应该将整个视图推到所需的缩进量上。

    使用笔尖时的注意事项: 您应该将约束(在这种情况下在 _imageView 和它的超级视图之间)定义为 >= 某个数字(在我的情况下是 20)。那么原始约束和layoutSubviews 中添加/删除的约束不会相互冲突。

    您还应该考虑在awakeFromNib中调用以下代码

    [_imageView setTranslatesAutoresizingMaskIntoConstraints:NO]
    

    这样旧的“弹簧和支柱”就不会妨碍您添加的约束。

    【讨论】:

      【解决方案6】:

      限制在界面生成器中自定义表格单元格的内容视图的前沿。对于一个简单的利润,这似乎就足够了。如果您需要以编程方式更改缩进,请参阅 Dean 的回答。或https://stackoverflow.com/a/7321461/5000071

      【讨论】:

        【解决方案7】:

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

        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 单元格的更好方法。

        【讨论】:

          【解决方案8】:

          在某些情况下,接受的答案可能会导致 iOS8 上的无限循环。所以最好只覆盖您的自定义UITableViewCellsetFrame 并在那里调整框架。

          -(void)setFrame:(CGRect)frame {
              float inset = self.indentationLevel * self.indentationWidth;
          
              frame.origin.x += inset;
              frame.size.width -= inset;
          
              [ super setFrame:frame ];
          }
          

          【讨论】:

            【解决方案9】:

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

            假设indentationWidth 已为单元格设置:

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

            【讨论】:

            • 我做了类似的事情,但我更新了updateConstraints 中的约束。我想这并没有太大的区别。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2011-05-21
            • 1970-01-01
            • 2023-01-16
            • 2013-11-21
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多