IndentationLevelForRowAtIndexPath не отступы пользовательской ячейки
Я переопределил метод 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;
}
Сначала я думал, что это не вызывается, но это была ошибка оператора (err, моя), и я не определил символ DEBUG = 1.
Однако он называется (duh me!), и это выход журнала:
-[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, который я определил в Interface Builder?
Если я изменил 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;
Ответы
Ответ 1
Да, похоже, что пользовательские ячейки таблицы не делают это автоматически? Вы должны переопределить метод 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()
}
Ответ 2
Вы добавили subviews вашего ProjectItemTableViewCell в cellView? Кроме того, вам нужно установить маски авторазведаний subviews, чтобы они были перемещены при изменении размера contentView.
Ответ 3
Как и в случае с принятым ответом, это можно сделать в 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:|-(%[email protected])-[_imageView]", indentPoints] options:0 metrics:nil views:views]];
[self addConstraints:_viewConstraints];
}
Если у вас есть ограничения AutoLayout, определяющие все остальное в представлении, тогда это должно вытолкнуть весь вид на желаемую величину отступа.
ПРИМЕЧАНИЕ при использовании Nib:
Вы должны определить ограничение (в данном случае между _imageView
и его супер-представлением) как >=
некоторое число (в моем случае это было 20). Тогда исходное ограничение и одно добавление/удаление в layoutSubviews
не конфликтуют друг с другом.
Вы также должны рассмотреть возможность вызова следующего в awakeFromNib
[_imageView setTranslatesAutoresizingMaskIntoConstraints:NO]
Это так, что старые "пружины и стойки" не мешают ограничениям, которые вы добавляете.
Ответ 4
Принятый ответ может привести к бесконечному циклу на iOS8 в некоторых случаях. Поэтому лучше просто переопределить setFrame
вашего пользовательского UITableViewCell
и настроить рамку там.
-(void)setFrame:(CGRect)frame {
float inset = self.indentationLevel * self.indentationWidth;
frame.origin.x += inset;
frame.size.width -= inset;
[ super setFrame:frame ];
}
Ответ 5
Вы случайно переопределили shouldIndentWhileEditing:
на NO
в свой собственный класс ячеек таблицы?
Ответ 6
Уровень отступов является свойством самого UITableViewCell
. Попробуйте установить его в ячейке при ее создании и вернуть это значение в tableView:indentationLevelForRowAtIndexPath:
Ответ 7
Ограничьте передний край представления содержимого пользовательской ячейки таблицы, которую вы имеете в построителе интерфейса. Для простой разницы это кажется достаточным. Если вам нужно программно изменить отступ, см. Ответ Дина. Или fooobar.com/questions/54898/....
Ответ 8
Я использовал этот код для отступов ячейки 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
)
Поэтому я не рекомендую использовать код выше, вместо этого я использую метод автоматического макета как ответ Дина с небольшой разницей (версия 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.
Ответ 9
Если вы используете пользовательскую ячейку со всеми ограничениями, наиболее удобным способом является установление ограничения, которое будет смещать весь контент с левого края, а затем обновлять его в соответствии с уровнем отступов в вашем подклассе ячейки.
Предполагая, что indentationWidth
уже установлен для ячейки:
override var indentationLevel: Int {
didSet {
self.leftConstraint.constant = CGFloat(self.indentationLevel) * self.indentationWidth
}
}