2009-08-30 14 views
14

Tengo algunas UITableViewCells que necesitan cambiar su altura dependiendo de la longitud de las cadenas dentro. Estoy calculando la altura necesaria dentro de tableView:cellForRowAtIndexPath: y luego la almacena en una variable (self.specialRowHeight). Entonces tengo:Obtener tableView: heightForRowAtIndexPath: pasar después de tableView: cellForRowAtIndexPath :?

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { 
    if (indexPath.section == SPECIAL_SECTION) { 
     return self.specialRowHeight; 
    } 
    else { 
     return 44; 
    } 
} 

Excepto que parece ser cada llamada antes de que el bit de tableView:cellForRowAtIndexPath:, por lo que es siempre cero.

¿Hay alguna forma de evitar esto, o quizás una forma diferente de hacerlo?

Gracias!

Respuesta

11

va a responder a mi propia pregunta aquí:

Originalmente yo estaba bastante seguro de que los cálculos de altura fueron atados al método tableView:cellForRowAtIndexPath:, y no se podían mover en otro lugar. Sin embargo, con un montón de reestructuraciones, pude sacar esas cosas de allí y entrar al tableView:heightForRowAtIndexPath:, que resuelve todo.

Para cualquier otra persona que está tratando de obtener células de auto-ajustable en altura para trabajar, aquí hay un código que podría ayudar:

// Inside tableView:cellForRowAtIndexPath: 
cell.textLabel.lineBreakMode = UILineBreakModeWordWrap; 
cell.textLabel.numberOfLines = self.numberOfTextRows; 
// numberOfTextRows is an integer, declared in the class 

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { 

    CGSize theSize = [theObject.theStringToDisplay sizeWithFont:[UIFont systemFontOfSize:18.0f] constrainedToSize:CGSizeMake(265.0f, 9999.0f) lineBreakMode:UILineBreakModeWordWrap]; 
    // This gets the size of the rectangle needed to draw a multi-line string 
    self.numberOfTextRows = round(theSize.height/18); 
    // 18 is the size of the font used in the text label 
    // This will give us the number of lines in the multi-line string 

    if ((indexPath.section == FIXED_HEIGHT_SECTION) || (self.numberOfTextRows < 2)) { 
     return 44; 
     // 44 is the default row height; use it for empty or one-line cells (or in other table sections) 
    } else { 
     return theSize.height + 16; 
     // 16 seems to provide a decent space above/below; tweak to taste 
    } 
} 

Si usted puede pensar en una manera más precisa para calcular la altura apropiada de la célula, Soy todo oídos. :)

+0

No estoy realmente seguro de por qué usted divide la altura rect por 18 y luego la multiplica de nuevo, pero aparte de eso lo hago de la misma manera. –

+0

Bueno, la primera división es averiguar cuántas filas son necesarias, así que puedo establecer 'cell.textLabel.numberOfLines' correctamente; si no configuro eso, todo se imprime en una línea. Pero sí, creo que podría usar 'theSize.height' en el último bit allí, en lugar de' self.numberOfTextRows'. – Triz

+0

Editado la respuesta para mayor claridad y simplificación. Funciona muy bien ahora. – Triz

0

Puede establecer self.numberOfLines en 0 una vez y funcionaría igual. (Si numberOfLines se establece en 0, la etiqueta utiliza tantas filas como sean necesarias.)

+0

Um ... numberOfTextRows es una propiedad de clase personalizada, por lo que no hará nada más que lo que yo le digo. ¿Estás pensando en cell.textLabel.numberOfLines? – Triz

+0

En cualquier caso, sí, se puede establecer 'cell.textLabel.numberOfLines' en' 0', pero aún así es útil saber el número real que se utilizará (para calcular la altura de fila adecuada, como aquí, por ejemplo) . También encuentro que el código resultante es mucho más claro, ya que "0" no es semánticamente útil de un vistazo. – Triz

-7

Mi solución fue llamar a la tableView:cellForRowAtIndexPath: dentro de la aplicación de la siguiente manera tableView:heightForRowAtIndexPath:

- (CGFloat)tableView:(UITableView *)aTableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { 

    [self tableView:aTableView cellForRowAtIndexPath:indexPath]; 
    return headerHeight; 
} 
+3

'tableView: heightForRowAtIndexPath:' se llama para cada fila (!) En su tableView. Debido a esto, no se deben usar llamadas costosas como 'tableView: cellForRowAtIndexPath:'. –

+0

No estoy seguro de por qué se votó esta opción, ya que este método le permite realizar pruebas en comparación con la altura real de la celda, incluso si la etiqueta no es el único contenido. Sin embargo, esto es muy caro. – Kyle

Cuestiones relacionadas