2009-07-02 17 views
8

Me gustaría agregar un botón a una celda de la tabla. El "Evento Borrar" en la aplicación de calendario me inspiró ... (un caso similar es "Compartir contacto" en la guía)UIButton en la celda UITableView como "Eliminar evento"

A partir de ahora hay

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 
    //..yadayadayada 
    cell = [tableView dequeueReusableCellWithIdentifier:@"buttonCell"]; 
    if (cell == nil) { 
    cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:@"buttonCell"] autorelease]; 
    } 
    UIButton *button = [UIButton buttonWithType:UIButtonTypeInfoDark]; 
    [button setBackgroundColor:[UIColor redColor]]; 
    button.titleLabel.text = @"Foo Bar"; 
    [cell.contentView addSubview:button]; 

que produce un botón, por cierto. Todavía no se ve cómo se supone que es (es obvio que nunca he tratado con botones en iPhone, todavía), pero ¿es este el enfoque correcto al menos?

+0

¿La acción resultante del botón será diferente dependiendo de la fila en la que se encuentre? (por ejemplo, enviar por correo electrónico el contacto actual en esta fila, etc.) –

+0

Si lo está, puede configurar la etiqueta del botón de cada celda para decir, la fila indexPath, y luego leer la etiqueta del remitente en el selector que se ejecuta en un toque. – mmc

+0

Bueno, como con "Eliminar evento", solo tendré un botón en la parte inferior de la IU, es decir, en la última fila. –

Respuesta

1

Sí, este es generalmente el enfoque correcto.

Un consejo:

  • Establecer la devolución de llamada para sus eventos de botón, por lo que en realidad hace algo cuando se hace clic.

    [myButton addTarget:self action:@selector(whatMyButtonShouldDo:) 
        forControlEvents:UIControlEventTouchUpInside]; 
    

EDITAR: Código Ajustado por el uso de un botón del sistema, lo que hace que una gran cantidad de lo que había escrito uneccessary.

+0

En su código de ejemplo, no hay necesidad de soltar el botón, ya que [UIButton buttonWithType:] devuelve una instancia liberada automáticamente. –

+0

Estás en lo correcto, copié eso del código * I * donde usé mi initWithFrame. Ajustando. – mmc

+0

Gracias por los comentarios. La sugerencia con liberación/liberación automática fue notada. ¿Es realmente necesario juguetear con el marco? Simplemente quiero que el botón llene toda la celda de la tabla (es decir, no se preocupe por la posición y el tamaño); "Eliminar evento" demuestra esto muy bien. –

1

Sí, está en el camino correcto, esa es la manera más fácil de agregar una subvista a una celda (la otra está subclasificando un UITableViewCell).

Compruebe el Apple guide para obtener más información.

19

La forma en que lo tiene ahora cada vez que se muestra una celda, está asignando un botón, estableciendo su valor y agregándolo al contentView de la celda. Cuando la celda se reutiliza (a través del dequeueReusableCellWithIdentifier) creará otro botón nuevo, agregándolo a la celda (encima del antiguo) etc. El hecho de que haya pasado por addSubview significa que cada botón retiene el recuento nunca pasará a cero por lo que todos se quedarán. Después de un tiempo de desplazarse hacia arriba y hacia abajo, la celda terminará con cientos de subvistas de botones que probablemente no es lo que usted desea.

Algunos consejos:

  • Nunca destinar cosas dentro de una llamada cellForRowAtIndexPath a menos que se hace cuando se está volviendo dequeueReusableCellWithIdentifier nula y estás inicializar la célula. En todos los demás momentos posteriores, se le devolverá la celda almacenada en caché que ya habrá configurado, de modo que todo lo que tiene que hacer es cambiar las etiquetas o los iconos. Deberá mover todo lo relacionado con la asignación de botones dentro del derecho condicional if después del código de asignación de celda.

  • El botón debe tener una posición y un objetivo establecidos para que haga algo cuando se toca. Si cada celda va a tener este botón, un buen truco es hacer que todos apunten al mismo método de destino, pero establezca el valor del botón tag en indexPath.row de la celda (fuera del bloque de asignación de celda, ya que varía para cada celda). El controlador de acceso común para el botón usaría el valor de etiqueta del remitente para buscar los datos subyacentes en la lista de orígenes de datos.

  • Llame al release en el botón después de haber hecho un addSubview. De esta forma, el recuento de retenciones caerá a cero y el objeto se liberará cuando se publique el padre.

  • En lugar de añadir el botón a través addSubview, puede devolverlo como el accessoryView para la célula por lo que no tiene que preocuparse de posicionamiento (a menos que ya se está utilizando el accessoryView para otra cosa - como la divulgación botones).

+1

Muchas gracias por los valiosos consejos y explicaciones. Un novato de programación de iPhone como yo seguramente aprecia eso. En cuanto a la sugerencia 4, como con "Eliminar evento"/"Compartir contacto", solo tendré un botón en la parte inferior de la IU, es decir, en la última fila. Entonces, no puede ser el accesorioView, pero tiene que llenar toda la fila. Todavía estoy luchando con eso. –

+2

Con respecto al n. ° 3, al soltar el botón se bloqueará la aplicación. Él no lo está adjudicando. – DougW

+0

¡Bonito escribir Ramin! – Jordan

7

Tomé un enfoque diferente para crear un equivalente al botón 'Eliminar evento' en la aplicación Calendario. En lugar de agregar un botón como subvista, agregué dos vistas de fondo (rojo y rojo oscuro, con agradables degradados) a las celdas y luego redondeé las esquinas y establecí el borde en gris.

El siguiente código crea una celda reutilizable (de la manera habitual). Las dos imágenes a las que se hace referencia ('redUp.png' y 'redDown.png') se tomaron de una captura de pantalla del botón 'Eliminar Evento' del calendario. (Eso parecía más rápido que crear degradados programáticamente.) Hay posibilidades de ajustar un poco más para acercarlo aún más a la apariencia del "Eliminar Evento" del Calendario, pero está bastante cerca.

La acción del botón se desencadena por el método de delegado tableView tableView: didSelectRowAtIndexPath: method.

// create a button from a table row like the Calendar's 'Delete Event' button 
// remember to have an #import <QuartzCore/QuartzCore.h> some above this code 

static NSString *CellWithButtonIdentifier = @"CellWithButton"; 

UITableViewCell *cell = [self dequeueReusableCellWithIdentifier:CellWithButtonIdentifier]; 
if (cell == nil) { 
    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellWithButtonIdentifier] autorelease]; 
    [[cell textLabel] setTextAlignment: UITextAlignmentCenter]; 

    UIImageView* upImage = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"redUp.png"]]; 
    UIImageView* downImage = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"redDown.png"]]; 

    [cell setBackgroundView: upImage]; 
    [cell setSelectedBackgroundView: downImage]; 

    [[upImage layer] setCornerRadius:8.0f]; 
    [[upImage layer] setMasksToBounds:YES]; 
    [[upImage layer] setBorderWidth:1.0f]; 
    [[upImage layer] setBorderColor: [[UIColor grayColor] CGColor]]; 

    [[downImage layer] setCornerRadius:8.0f]; 
    [[downImage layer] setMasksToBounds:YES]; 
    [[downImage layer] setBorderWidth:1.0f]; 
    [[downImage layer] setBorderColor: [[UIColor grayColor] CGColor]]; 

    [[cell textLabel] setTextColor: [UIColor whiteColor]]; 
    [[cell textLabel] setBackgroundColor:[UIColor clearColor]]; 
    [cell setBackgroundColor:[UIColor clearColor]]; // needed for 3.2 (not needed for later iOS versions) 
    [[cell textLabel] setFont:[UIFont boldSystemFontOfSize:20.0]]; 

    [upImage release]; 
    [downImage release]; 
} 
return cell; 
+2

Debería agregar '[cell.textLabel setShadowColor: [UIColor blackColor]]; [cell.textLabel setShadowOffset: CGSizeMake (0, -1)]; 'al código. Eso le da al texto un efecto ligeramente realzado, por lo que se parece más al botón nativo. – Greg

Cuestiones relacionadas