2009-09-06 9 views
20

Tengo un UITableView donde, en algunos casos, ciertas secciones tienen cero filas. Mi objetivo es que cuando esto sea cierto, no quiero perder ningún espacio en la vista de tabla, debería parecer que no hay datos.UITableView No respetando heightForHeaderInSection/heightForFooterInSection?

El problema que tengo es con el encabezado y el pie de página para las secciones, que se muestran incluso si no hay una fila y, a pesar de que anulo el método de delegado para devolver 0.0f.

Esto es lo que parece: se puede ver ~ 20p de espacio gris en la parte superior, encabezados y pies de página de aproximadamente 10p cada uno para una sección con 0 filas.

alt text http://www.hanchorllc.com/table_cells.png

Aquí es mi seudo código:

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { 
    if ([section hasRow]) { 
      return 10.0f; 
    } else { 
      return 0.0f; 
    } 
} 



- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section { 
    if ([section hasRow]) { 
      return 10.0f; 
    } else { 
      return 0.0f; 
    } 
} 

He comprobado que estos métodos están siendo llamados y que la ruta correcta ejecución está teniendo lugar.

Una arruga: este controlador de vista usa un XIB y UITableView tiene los valores de encabezado y pie de página establecidos en 10.0 (valor predeterminado), aunque pensé que el método delegado lo reemplazó, si se implementó.

Esta es una aplicación dirigida a 3.0.

¿Qué estoy haciendo mal?

Respuesta

24

En un UITableView "agrupado" en el iPhone, seguirá representando una altura mínima para el encabezado y el pie de página, haciendo caso omiso de su código para establecerlo en cero. No está vinculado al valor por defecto de XIB.

Esto se debe a que un encabezado o pie de sección de altura cero se vería muy extraño. Por lo tanto, Apple ha decretado que una altura de encabezado no se puede establecer en 0. Y, por lo tanto, múltiples secciones "vacías" se renderizarán de forma extraña según su captura de pantalla.

Me temo que es todo porque vas por el camino equivocado al borrar el tamaño del encabezado cuando no hay filas de datos; en su lugar, debe no llamar a ningún método para las secciones vacías. Es una técnica mala porque esencialmente el iPhone tiene que llamar a más métodos de los que debería, y también renderiza más encabezados de los que desea (generalmente, algunas veces la gente quiere dejar los encabezados en blanco allí, por ejemplo para arrastrar y soltar) .

Así que, por ejemplo, imaginemos que tiene varias secciones, pero solo algunas tienen más de una fila (quizás en función de los filtros/configuraciones del usuario).

El mal forma de implementar es:

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 
    return totalNumberOfPossibleSections; 
} 

y luego para cada sección tiene ningún resultado para:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 
    if (![section hasRow]) return 0; 
} 

y

- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section { 
    if (![section hasRow]) return 0.0f; 
} 

El correcta forma de imp lementing es:

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 
    return numberOfSectionsWhichHaveAtLeastOneRowInThem; 
} 

y cada sección tendrá al menos un resultado.De esta forma, las secciones sin datos ni siquiera se representan, ni siquiera se solicitan métodos. Nota: mis dos nombres de variable están compuestos para transmitir lo que contendrán. No son variables especiales de Apple ...

Espero que ayude!

+0

Sí, esto suena razonable. He adquirido el hábito de declarar constantes enum para los diseños de sección de la tabla y estaba tratando de forzar a este controlador en particular en ese diseño, que no funciona muy bien con un número desconocido de filas en las secciones. Es extraño que la documentación de Apple no indique en ningún lugar (que pueda encontrar) que no aceptará 0.0 como valor, especialmente porque * puede * establecer 0.0 en el XIB (y sí, se ve realmente raro). Puedo archivar un error de doco, ya que al menos debe tenerse en cuenta que el valor debe ser mayor que 0.0f. Saludos. – Hunter

+0

De hecho, se ve raro. Tampoco lo he visto en ninguna de la documentación, por lo que probablemente valga la pena archivarlo como un error. – h4xxr

+0

Esta es una buena idea, pero tuve problemas para implementarla. Tengo instrucciones de cambio para la sección en un montón de mis métodos de tabla de vista. Devolver un número variable de secciones según el contenido de los datos realmente arruina esta asignación y no puedo pensar en una forma elegante (o incluso fácil) de manejarlo. – blindjesse

0

En realidad, conmigo sucede en otro lado. He asignado un encabezado de sección para que sea 10 en xib, pero para la primera sección, quiero un encabezado de encabezado de tamaño. Estoy usando este método en mi UITableViewCotroller

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    if(indexPath.section==0) 
     return 125; 
    return tableView.rowHeight; 
} 

Pero las alturas de la sección de cabecera no se cambian, a pesar de que el método está recibiendo llamadas.

3

que tenía un problema similar: Estaba preparando un UITableView de un XI ter (igual que usted), y suministra una altura de 0 a algunos pies de página con la sección tableView:heightForFooterInSection (igual que usted), pero fue ignorado el valor.

La solución es simple: también establece la altura del pie de página en 0.0 en el XIB. (En Interface Builder seleccione la Vista de tabla, presione Command-3 para ver el Inspector de tamaño, busque el campo de altura del pie de página cerca de la parte superior)

Una vez hecho esto, obedeció la altura personalizada del pie de página como se esperaba. (Tal vez se trata a la altura de pie de página XI ter como mínimo?)

+0

En IB, la altura mínima de sección que puede establecer para una vista de tabla agrupada es 1. Por lo tanto, esto no cambia nada. –

1

Funciona para mí:

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section 
{ 
    tableView.sectionHeaderHeight = (section == 0 ? 10 : 0); 
    return tableView.sectionHeaderHeight; 
} 

- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section 
{ 
    tableView.sectionFooterHeight = (section == 0 ? 20 : 4); 
    return tableView.sectionFooterHeight; 
} 
9

Parece ser que la mesa respeta tableView:heightForHeaderInSection: sólo si tableView:viewForHeaderInSection: no es nil, o si tableView:titleForHeaderInSection: no es nil o @"". Lo mismo es cierto, respectivamente, para las alturas del pie de página.

Así que asumiendo que no tiene ninguna vistas sección de encabezado o títulos, sólo tiene que añadir esto a su mesa delegado:

- (UIView*)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section { 
    return [[[UIView alloc] initWithFrame:CGRectZero] autorelease]; 
} 
+0

Esto no es verdad.Si devuelve 0 en tableView: heightForHeaderInSection :, obtendrá un pie de página de 10 puntos de altura. Tendrás que especificar un número ligeramente mayor como 0.00001f ya que @Juris menciona su respuesta. – Klaas

0

Mi solución a este problema está encendido y apagado cómo h4xxr está describiendo sin embargo, tengo un enfoque ligeramente diferente para construir un número dinámico de secciones.

En primer lugar, defino un método que recorrerá mi estructura de datos e indicará si los datos deben mostrarse en la tabla. Esta bandera se almacena en una matriz para que pueda incluir las pocas o tantas secciones como quiera. Puedo describir esta implementación un poco mejor si nos centramos solo en el número de celdas de cada sección:

Supongamos que mi primera sección debe ser detalles de contacto con nombre, apellido y antigüedad. Definiré esta sección con una identificación de '1' (aunque técnicamente como explico más adelante podría ser cualquier número). Ahora, si mi método determina que esta sección debe ser visible, presiono el valor '1' en una matriz.

La próxima sección que deseo mostrar es la dirección y puede tener 3-4 filas/celdas. Como arriba, la lógica en mi método determina si la dirección debe ser visible presionando '2' en la matriz.

Ahora ... si quisiéramos ambas secciones visibles, tendríamos una matriz con una longitud de 2 y dos elementos [1,2]. Si solo quisiéramos que los detalles de contacto estuvieran visibles, nuestra matriz tendría una longitud de 1 con elementos [1] y [2] solo para la dirección.

Ahora podemos devolver la longitud de nuestra matriz para definir el número de secciones que queremos.

nuestra sentencia switch tendrá ahora un aspecto como si algo como esto:

switch(ourArray[indexPath.section]){ 
    case 1: 
     <Return the number of rows for the contact details which we said would be 3> 
     break; 
    case 2: 
     <Return the number of rows for the address details which we said would be 4> 
     break; 
    case 3: 
     <Return another number for some section that is referenced by the id '3'> 
     break; 
} 

Aviso He puesto el caso 3 en mi interruptor. Debido a que la matriz de nuestro ejemplo solo contiene los valores '1' y '2', el caso 3 nunca se igualaría y se ignoraría a menos que decidiéramos agregar/habilitar este caso presionándolo en la matriz.

Tenga en cuenta también que en nuestro método, que define la lógica de qué secciones son visibles, cambie el orden de las secciones insertándolas/empujándolas en diferentes ubicaciones de la matriz.

Utilizo lo anterior religiosamente, ya que me permite desacoplar la indexación y la construcción de secciones.

Finalmente, antes de actualizar mi tabla usando 'reloadData' llamaré a mi método, que construirá la matriz y proporcionará la longitud y secuencia correctas de identificadores de sección para permitir que mi tableview sepa cómo compilarse. Si mis datos cambian o se filtra de alguna manera, volveré a llamar a este método y reconstruir la matriz.

32

Esto es un poco complicado, ya que no se acepta el valor 0.0f. pero cualquier cosa lo suficientemente cerca de cero hará el truco. Si decide no ser perfecto como un píxel y desea los números redondos, entonces 1.0f hará casi lo mismo, ya que una diferencia de 1px en altura será bastante notable.

-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{ 
    if(section == 1) 
     return 0.000001f; 
    else return 44.0f; // put 22 in case of plain one.. 
} 

-(CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section{ 
    return 0.000001f; //removing section footers 
} 
+0

Wow. Esto es muy complicado pero funciona. – nonamelive

+1

Parece que este hack no funciona en iOS 7. – crishoj

+1

Un truco tremendo.Después de pasar un día en heightForHeaderInSection y heightForFooterInSection esto funcionó para mí. Y también funciona en iOS 7 :) – Machete

1

me encontré con que en mi caso se necesitan 2 cosas para matar el pie fantasma:

1) establecer la vista de tabla sectionFooterHeight a 0, es decir, en viewDidLoad añadiendo:

tableView.sectionFooterHeight = 0 

2) agregando el método delegado:

override func tableView(tableView: UITableView, viewForFooterInSection section: Int) -> UIView? { 
    return UIView(frame: CGRect.zero) 
} 

(usando Swift 2.2)

Cuestiones relacionadas