indentationLevelForRowAtIndexPath не имеет отступа для пользовательской ячейки - PullRequest
19 голосов
/ 23 марта 2010

Я переопределил метод 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;
}

Как сделать отступ для пользовательского 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 ]

45 голосов
/ 07 октября 2010

Да, кажется, что пользовательские ячейки таблицы не делают это автоматически? Вам необходимо переопределить метод layoutSubviews в классе ячейки таблицы. См. этот вопрос о том, как это сделать.

Этот код отлично сработал для меня (хотя будьте осторожны, если вы устанавливаете пользовательскую высоту с делегатом, они, похоже, мешают друг другу):

- (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()
}
3 голосов
/ 22 декабря 2017

Если вы используете пользовательскую ячейку с ограничениями, наиболее удобный способ - установить ограничение, которое будет сдвигать весь контент от левого края, а затем обновить его в соответствии с уровнем отступа в подклассе вашей ячейки.

Предполагается, что indentationWidth уже установлено для ячейки:

override var indentationLevel: Int {
    didSet {
        self.leftConstraint.constant = CGFloat(self.indentationLevel) * self.indentationWidth
    }
}
1 голос
/ 24 февраля 2016

Принятый ответ может привести к бесконечному циклу на iOS8 в некоторых случаях. Так что лучше просто переопределить setFrame вашего пользовательского UITableViewCell и отрегулировать кадр там.

-(void)setFrame:(CGRect)frame {
    float inset = self.indentationLevel * self.indentationWidth;

    frame.origin.x += inset;
    frame.size.width -= inset;

    [ super setFrame:frame ];
}
1 голос
/ 22 сентября 2014

Аналогично принятому ответу, это то, как это можно сделать в iOS 8, при этом вместо этого используется layoutSubviews с AutoLayout.

С _viewConstraints в качестве NSMutableArray ивара и _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]

Это так, что старые «пружины и распорки» не мешают добавляемым ограничениям.

1 голос
/ 23 марта 2010

Добавили ли вы подпредставления вашей ProjectItemTableViewCell в contentView ячейки? Кроме того, вам нужно установить маски авторазмера подпредставлений, чтобы они могли перемещаться при изменении размера contentView.

0 голосов
/ 17 декабря 2015

Я использовал этот код для отступа в ячейке tableView. Первоначально это работало хорошо, но позже это вызвало некоторую проблему (например, вмешательство в мое динамическое обновление высоты UITextView при отступе, которое является подпредставлением моей ячейки tableView. Каким-то образом мой UITextView считает, что его ширина все еще является шириной исходного содержимого ContentView). 1001 *

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
)

Так что я не рекомендую код выше, вместо этого я использую метод автоматического размещения в качестве ответа Дина с небольшой разницей (версия 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.

0 голосов
/ 02 июля 2015

Придерживайтесь переднего края представления содержимого пользовательской ячейки таблицы, которая есть в конструкторе интерфейсов. Для простого запаса этого, кажется, достаточно. Если вам нужно программно изменить отступ, см. Ответ Дина. Или https://stackoverflow.com/a/7321461/5000071.

0 голосов
/ 23 марта 2010

Уровень отступа является свойством самого UITableViewCell. Попробуйте установить его в ячейке при его создании и вернуть это значение в tableView:indentationLevelForRowAtIndexPath:

0 голосов
/ 23 марта 2010

Вы случайно переопределили shouldIndentWhileEditing: в NO в своем пользовательском классе ячеек таблицы?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...