Cómo establecer el ancho de una celda en un UITableView en estilo agrupado

107

He estado trabajando en esto durante aproximadamente 2 días, así que pensé en compartir mis aprendizajes con ustedes.

La pregunta es: ¿Es posible reducir el ancho de una celda en un UITableView agrupado?

La respuesta es no.

Pero hay dos formas de solucionar este problema.

Solución n. ° 1: una tabla más delgada Es posible cambiar el marco de tableView para que la tabla sea más pequeña. Esto dará como resultado que UITableView renderice la celda interior con el ancho reducido.

Una solución para esto puede verse así:

-(void)viewWillAppear:(BOOL)animated
{
    CGFloat tableBorderLeft = 20;
    CGFloat tableBorderRight = 20;

    CGRect tableRect = self.view.frame;
    tableRect.origin.x += tableBorderLeft; // make the table begin a few pixels right from its origin
    tableRect.size.width -= tableBorderLeft + tableBorderRight; // reduce the width of the table
    tableView.frame = tableRect;
}

Solución # 2: tener celdas renderizadas por imágenes

Esta solución se describe aquí: http://cocoawithlove.com/2009/04/easy-custom-uitableview-drawing.html

Espero que esta información le sea útil. Me tomó alrededor de 2 días probar muchas posibilidades. Esto es lo que quedó.

Tomen
fuente
3
Creo que esto debería haberse configurado como una pregunta con solo la segunda línea ("La pregunta es: ..."), luego la Solución n. ° 1 y la Solución n. ° 2 publicadas como dos respuestas separadas, y una de ellas será aceptada. Luego, si otros usuarios agregan sus propias respuestas y una de ellas termina siendo mejor, la respuesta aceptada se puede cambiar más adelante.
GeneralMike

Respuestas:

226

Una forma mejor y más limpia de lograr esto es subclasificar UITableViewCell y anular su -setFrame:método de esta manera:

- (void)setFrame:(CGRect)frame {
    frame.origin.x += inset;
    frame.size.width -= 2 * inset;
    [super setFrame:frame];
}

¿Por qué es mejor? Porque los otros dos son peores.

  1. Ajustar el ancho de la vista de la tabla en -viewWillAppear:

    En primer lugar, esto no es confiable, la supervista o el controlador de vista principal pueden ajustar el marco de la vista de la tabla más allá de la -viewWillAppear:llamada. Por supuesto, puede subclasificar y anular -setFrame:para su UITableView tal como lo hago aquí para UITableViewCells. Sin embargo, la subclasificación de UITableViewCells es una forma muy común, ligera y de Apple.

    En segundo lugar, si su UITableView tiene backgroundView, no desea que su backgroundView se reduzca juntos. Mantener el ancho de backgroundView mientras se reduce el ancho de UITableView no es un trabajo trivial, sin mencionar que expandir las subvistas más allá de su supervista no es algo muy elegante para hacer en primer lugar.

  2. Representación de celda personalizada para simular un ancho más estrecho

    Para hacer esto, debe preparar imágenes de fondo especiales con márgenes horizontales y debe diseñar las subvistas de las celdas usted mismo para acomodar los márgenes. En comparación, si simplemente ajusta el ancho de toda la celda, el tamaño automático hará todo el trabajo por usted.

an0
fuente
2
esta es una solución agradable y elegante, lo hice en una categoría :) También señalaría que los objetos más transparentes, más carga de CPU :)
mister koz
11
@misterkoz: una advertencia: algunos controles de iOS (UIDatePicker para definir) usan internamente UITableViewCells y se rompen si implementa esto en una categoría.
Clafou
7
Este método no parece funcionar en iOS8 cuando se intenta eliminar una celda en modo de edición. Se llama a setFrame cuando ingresa / sale del modo de edición, por lo que la celda sigue encogiéndose. ¿Alguna solución a esto?
John Baum
3
@JohnBaum esto podría ayudar (al menos en mi caso funciona): stackoverflow.com/questions/25911484/ios-8-cell-resizing/…
HashtagMarkus
2
Esta solución es verdaderamente un regalo del cielo. En caso de que alguien se pregunte cómo hacer lo mismo en swift - reddit.com/r/swift/comments/2fr849/…
sysuser
16

Para hacer esto en Swift, que no proporciona métodos para establecer variables, tendrá que anular el establecedor para frame. Publicado originalmente (al menos donde lo encontré) aquí

override var frame: CGRect {
    get {
        return super.frame
    }
    set (newFrame) {
        let inset: CGFloat = 15
        var frame = newFrame
        frame.origin.x += inset
        frame.size.width -= 2 * inset
        super.frame = frame
    }
}
JuJoDi
fuente
Funciona para Swift
Simon McNeil
9

Si nada funciona, puedes probar esto

Haga que el color de fondo de la celda sea un color claro y luego coloque una imagen de la celda con el tamaño requerido. Si desea mostrar algo de texto en esa celda, coloque una etiqueta sobre la imagen. No olvide establecer el color de fondo de la etiqueta también en color claro.

Inclúyeme
fuente
8

Descubrí que la solución aceptada no funcionaba con la rotación. Para lograr UITableViewCells con anchos fijos y márgenes flexibles, acabo de adaptar la solución anterior a lo siguiente:

- (void)setFrame:(CGRect)frame {

    if (self.superview) {
        float cellWidth = 500.0;
        frame.origin.x = (self.superview.frame.size.width - cellWidth) / 2;
        frame.size.width = cellWidth;
    }

    [super setFrame:frame];
}

El método se llama siempre que el dispositivo gira, por lo que las celdas siempre estarán centradas.

Graham
fuente
0

Hay un método que se llama cuando se gira la pantalla: viewWillTransitionToSize

Aquí es donde debes cambiar el tamaño del marco. Ver ejemplo. Cambie las coordenadas del marco según sea necesario.

- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
{
    [coordinator animateAlongsideTransition:nil completion:^(id<UIViewControllerTransitionCoordinatorContext> context)
    {
        int x = 0;
        int y = 0;
        self.tableView.frame = CGRectMake(x, y, 320, self.tableView.frame.size.height);
    }];
}
Chico
fuente
-2

lo hago en

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell;
    CGFloat tableBorderLeft = self.view.frame.origin.x + 10;
    CGFloat tableBorderRight = self.view.frame.size.width - 20;

    CGRect tableRect = self.view.frame;
    tableRect.origin.x = tableBorderLeft; 
    tableRect.size.width = tableBorderRight; 
    tableView.frame = tableRect;
}

Y esto funcionó para mi

Lều Đức Quý
fuente
-6

En el archivo .h agregue el delegado 'UITableViewDataSource'

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{ 
    return size;
}
bharath gangupalli
fuente
4
Quiere establecer el ancho, no la altura
Christopher Pickslay
oh hoo. sry por las molestias.
bharath gangupalli
Usted malinterpreta la pregunta y responde por la altura y sabe lo que funciona para mí porque estoy buscando la altura, no el ancho ... gracias por la respuesta
Pooja