2012-01-31 11 views
11

Estoy tratando de usar mi ReusableCell para las celdas con imágenes en diferentes dimensiones. Las imágenes se colocan dentro de una caja negra de 220x150 con una escala de UIViewContentModeScaleAspectFit.UITableViewCell con imágenes en diferentes dimensiones

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    static NSString *CellIdentifier = @"NewsTableViewCell"; 

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 
    if (cell == nil) { 
     cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; 
    } 

    NewsItem *item = [self.fetchedResultsController objectAtIndexPath:indexPath]; 

    NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:item.imageUrl]]; 
    [cell.imageView setImage:[[UIImage alloc] initWithData:data]]; 
    [cell.imageView setBackgroundColor:[UIColor blackColor]]; 
    [cell.imageView setContentMode:UIViewContentModeScaleAspectFit]; 

    CGRect imageViewFrame = cell.imageView.frame; 
    imageViewFrame.size.width = 220; 
    imageViewFrame.size.height = 150 
    [cell.imageView setFrame:imageViewFrame]; 

    [cell.textLabel setText:item.title]; 

    return cell; 
} 

Los anteriores resultados de código en un diseño como el de abajo y las imágenes son a veces cambian cuando se desplaza en la vista de tabla.

UITableView with images

En lugar de esta disposición no estructurada, me gustaría que las imágenes se alinean así:

Images in a black box

¿qué estoy haciendo mal con este ReusableCell?

EDIT1:

Estoy intentando crear un imageView y añadir esta imageView como supervista a cell.contentView.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    static NSString *CellIdentifier = @"NewsTableViewCell"; 

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 
    if (cell == nil) { 
     cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; 
    } 

    NewsItem *item = [self.fetchedResultsController objectAtIndexPath:indexPath]; 

    UIImage *placeholderImage = [UIImage imageNamed:@"ImagePlaceholderThumb"]; //220x150 

    UIImageView *imageView = [[UIImageView alloc] initWithImage:placeholderImage]; 

    NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:item.imageUrl]]; 
    [imageView setImage:[[UIImage alloc] initWithData:data]]; 
    [imageView setBackgroundColor:[UIColor blackColor]]; 
    [imageView setContentMode:UIViewContentModeScaleAspectFit]; 

    CGRect imageViewFrame = imageView.frame; 
    imageViewFrame.size.width = placeholderImage.size.width; 
    imageViewFrame.size.height = placeholderImage.size.height; 
    [imageView setFrame:imageViewFrame]; 

    [cell.contentView addSubview:imageView]; 

    [cell.textLabel setText:item.title]; 

    return cell; 
} 

Los anteriores resultados de código en el siguiente:

UIImageView in superview

Es como algunas de las imágenes son visibles en dos células. Parece que no mantienen el tamaño que he establecido en el imageViewFrame. ¿Sabes por qué?

+0

Lo que está buscando se llama letter boxing y AFAIK es algo que UIKit no hará por usted a menos que lo haga usted mismo. – Till

+0

Entonces, ¿cómo puedo hacer esto yo mismo? – dhrm

+0

Ver el comentario en mi propia respuesta. Además, como un lado, la forma en que está creando el UIImageView y cargando sus datos está sucediendo CADA vez que la celda se vuelve visible desde fuera de la pantalla. Es posible que vea algunos desplazamientos incompletos. Me gustaría dos cosas de manera diferente: 0) cargar los datos de imagen de forma asíncrona y almacenarlos en caché con algo como EGOImageView, 1) Generalmente, si desea crear las subvistas de una celda al crear la celda, solo desea cambiar el contenido de las subvistas después// Configurar la celda ... – Keller

Respuesta

18

Una solución rápida estaría utilizando el modo de contenido UIViewContentModeScaleAspectFill. Las imágenes se extenderán en una o ambas dimensiones para llenar los límites de la vista de la imagen completa.

Realmente necesita la subclasificación UITableViewCell para hacer esto bien.

Thre es una solución perezoso añadiendo un nuevo UIImageView y el uso de un espaciador, como Keller le dijo en su respuesta (no dude en aceptar su respuesta, esto es sólo el código que falta).

Extracto de tableView:cellForRowAtIndexPath::

... 
cell.textLabel.text = [NSString stringWithFormat:@"Cell #%i", indexPath.row]; 
cell.imageView.image = [UIImage imageNamed:@"spacer.png"]; /* spacer is 64 x 44 */ 
/* image view width should be ~ 64 px, otherwise it will overlap the text */ 
UIImageView *iv = [[UIImageView alloc] initWithFrame:(CGRect){.size={64, tableView.rowHeight}}]; 
switch (indexPath.row) { 
    case 0: 
     iv.image = [UIImage imageNamed:@"waterfall.png"]; 
     break; 
    /* etc... */ 
} 
if (indexPath.row < 3) { 
    /* add black bg to cell w/ images */ 
    iv.backgroundColor = [UIColor blackColor]; 
} 
iv.contentMode = UIViewContentModeScaleAspectFit; 
[cell.contentView addSubview:iv]; 
... 

La tabla se verá así: aspect fit

Deberá ajustar el marcador de posición (spacer.png arriba) en la vista de la imagen existente de la célula. Empujará la etiqueta de texto hacia la derecha.

Puede utilizar aspecto llenar y quitar el bit de color de fondo:

iv.contentMode = UIViewContentModeScaleAspectFill; 

La tabla se verá mal porque la imagen se dibuja OutSite los límites:

aspect fill without clipping

Sólo clip de límites para obtener un mejor resultado:

iv.clipsToBounds = YES; 

aspect fill

+0

Lo siento, pero ahora es una solución para mí. Necesito las imágenes para mantener su relación. – dhrm

+0

La relación se mantiene, solo la imagen completa no será visible. De todos modos, no es tan fácil como dije. Ver respuesta actualizada. – djromero

2

Cree una subvista UIImageView para cada celda y para el contentView. Cada UIImageView contiene una imagen con un marco consistente pero con la opción UIViewContentModeScaleAspectFit. Luego simplemente establece el color de fondo del UIImageView en negro.

Acabo de confirmar que esto funciona, pero también necesita crear una imagen espaciadora de marcador de posición para asegurarse de que la etiqueta de texto se salga del camino. Simplemente haga que tenga las mismas dimensiones de su imagen (con el boxeo de letras).

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    static NSString *CellIdentifier = @"Cell"; 

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 
    if (cell == nil) { 
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; 

    //spacer 
    cell.imageView.image = [UIImage imageNamed:@"placeholder"]; 

    //imageview 
    UIImageView *thumbnail = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 80, 44)]; 
    thumbnail.tag = kThumbTag; 
    thumbnail.backgroundColor = [UIColor blackColor]; 
    thumbnail.contentMode = UIViewContentModeScaleAspectFit; 
    [cell.contentView addSubview:thumbnail]; 
    } 

    // Configure the cell... 

    cell.textLabel.text = [NSString stringWithFormat:@"Cell %d", indexPath.row]; 

    cell.imageView.frame = CGRectMake(0, 0, 80, 44); 

    UIImageView *thumb = (UIImageView*)[cell.contentView viewWithTag:kThumbTag]; 
    if (indexPath.row == 0) { 
    [thumb setImage:[UIImage imageNamed:@"image1.png"]]; 
    } else { 
    [thumb setImage:[UIImage imageNamed:@"image2.png"]]; 
    } 

    return cell; 
} 

Obviamente, este ejemplo no es perezosa cargar las imágenes (no me había dado cuenta que estaba cargarlos desde una URL). Para eso, usaría una subclase con EGOImageView o algo por el estilo.

+0

Gracias por la solución. ¿Podría echar un vistazo a mi 'EDIT1'? – dhrm

+0

Me di cuenta de que su imagen de marcador de posición tiene un tamaño de fotograma de 220 x 150 - ¿es realmente 150px la altura que desea para su celda? Si es así, solo necesita establecer cell.rowHeight (en su plumín o en viewDidLoad). De lo contrario, solo asegúrese de que la imagen de marcador de posición sea del tamaño de fotograma correcto que está buscando o cambie el tamaño de su fotograma. – Keller

+0

En realidad, también podría usar el método delegado UITableView 'indentationLevelForRowAtIndexPath' – Keller

Cuestiones relacionadas