iphone - uitableviewcell - uitableviewcontroller swift 4
indentationLevelForRowAtIndexPath no indenta la celda personalizada (9)
He anulado el método tableView:indentationLevelForRowAtIndexPath
en mi clase derivada UITableViewController
siguiente manera:
- (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;
}
Inicialmente pensé que no se estaba llamando pero que era un error del operador (err, mío) y no había definido el símbolo DEBUG = 1.
Sin embargo, se está llamando (duh me!) Y esta es la salida del registro:
-[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
Pero, esto no está afectando el diseño de las celdas. Sin sangría.
Esta es mi implementación itemCellForRowAtIndexPath
, si eso hace alguna diferencia:
-(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;
}
¿Cómo sangrar un UITableViewCell
personalizado que he definido en Interface Builder?
Si cambio el itemCellForRowAtIndexPath
para usar un UITableViewCell
predeterminado con el código a continuación, entonces se sangra bien.
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;
¿Ha agregado las subvistas de su ProjectItemTableViewCell al contentView de la celda? Además, debe configurar las máscaras de tamaño automático de las subvistas para que se vuelvan a colocar cuando cambie el tamaño de contentView.
¿Ha anulado accidentalmente shouldIndentWhileEditing:
to NO
en su clase de celda de tabla personalizada?
El nivel de sangría es una propiedad del propio UITableViewCell
. Intente configurarlo en la celda cuando lo cree, y devuelva este valor en tableView:indentationLevelForRowAtIndexPath:
La respuesta aceptada podría llevar a un bucle infinito en iOS8 en algunos casos. Por lo tanto, es mejor simplemente anular setFrame
de su UITableViewCell
personalizado y ajustar el marco allí.
-(void)setFrame:(CGRect)frame {
float inset = self.indentationLevel * self.indentationWidth;
frame.origin.x += inset;
frame.size.width -= inset;
[ super setFrame:frame ];
}
Restrinja al borde inicial de la vista de contenido de la celda de tabla personalizada que tiene en el generador de interfaces. Para un margen simple, esto parece ser suficiente. Si necesita cambiar la sangría programáticamente, vea la respuesta de Dean. O https://.com/a/7321461/5000071 .
Sí, parece que las celdas de tabla personalizadas no hacen esto automáticamente? layoutSubviews
anular el método layoutSubviews
en la clase de celda de tabla. Vea esta pregunta para saber cómo hacer esto.
Este código funcionó perfectamente para mí (aunque tenga cuidado si está configurando una altura personalizada con el delegado también, parecen interferir entre sí):
- (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
);
}
Editar para iOS8 y versiones posteriores
Lo anterior funciona para mí en iOS, pero también causa errores sutiles al intentar autoajustar la altura de la celda. Hay una solución más sencilla: si tiene la reproducción automática activada para la celda, simplemente configure el margen izquierdo de contentView:
override func layoutSubviews() {
super.layoutSubviews()
self.contentView.layoutMargins.left = CGFloat(self.indentationLevel) * self.indentationWidth
self.contentView.layoutIfNeeded()
}
Si usa una celda personalizada con restricciones, la forma más conveniente es configurar una restricción que cambie todo el contenido desde el borde izquierdo y luego actualizarlo de acuerdo con el nivel de sangría en su subclase de celda.
Suponiendo que indentationWidth
ya está configurado para la celda:
override var indentationLevel: Int {
didSet {
self.leftConstraint.constant = CGFloat(self.indentationLevel) * self.indentationWidth
}
}
Similar a la respuesta aceptada, esta es la forma en que se puede hacer en iOS 8 mientras se siguen usando layoutSubviews
con layoutSubviews
.
Con _viewConstraints
como un NSMutableArray
ivar y _imageView
como la vista más cercana al lado izquierdo de la vista de contenido de la celda.
- (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];
}
Si tiene restricciones de AutoLayout que definen todo lo demás en la vista, esto debería empujar a la vista completa sobre la cantidad de sangría deseada.
NOTA si usa Nib: Debe definir la restricción (en este caso entre _imageView
y su vista _imageView
) como >=
algún número (en mi caso fue 20). Luego, la restricción original y la que se agrega / elimina en layoutSubviews
no entran en conflicto entre sí.
También debe considerar llamar a lo siguiente en awakeFromNib
[_imageView setTranslatesAutoresizingMaskIntoConstraints:NO]
Esto es para que los viejos "resortes y puntales" no interfieran con las restricciones que está agregando.
Utilicé este código para sangrar mi celda tableView. Inicialmente funcionó bien, pero más tarde esto causó algún problema (por ejemplo, interferir con mi actualización dinámica de altura de UITextView cuando está sangrada, que es una subvista de mi celda tableView. De alguna manera, mi UITextView cree que su ancho aún es el ancho del contentView original).
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
)
Así que no recomiendo el código anterior, en lugar de eso, uso el método de diseño automático como la respuesta de Dean con una pequeña diferencia (versión 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
}
El "indentConstraint" es un IBOutlet (restricción principal con contentView), y el código está escrito en una subclase tableViewCell personalizada, funcionó a la perfección, y no es necesario eliminar o agregar ninguna restricción, lo que es más costoso. Creo que el método de diseño automático es la mejor manera de sangrar la celda tableView.