2009-07-02 4 views
8

Vorrei aggiungere un pulsante a una cella di tabella. Il "Elimina evento" in app calendario mi ha ispirato ... (un caso simile è "Condividi Contatta" in contatti)UIButton nella cella UITableView come "Delete Event"

A partire da ora c'è

- (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]; 

che produce un pulsante, anzi. Non sembra ancora come dovrebbe (è ovvio che non ho mai avuto a che fare con i pulsanti di iPhone), ma questo è almeno l'approccio giusto?

+0

Sarà l'azione risultante del pulsante essere diversa a seconda di quale fila è in? (Ad esempio e-mail il contatto corrente in questa riga, ecc ...) –

+0

Se lo è, è possibile impostare il tag di tasto di ogni cella a dire, la fila indexPath, e poi leggere il tag del mittente nel selettore che viene eseguito con un tocco – mmc

+0

Bene, come con "Elimina evento" Avrò un solo pulsante nella parte inferiore dell'interfaccia utente, ad esempio nell'ultima riga. –

risposta

1

Sì, questo è generalmente l'approccio corretto.

Un consiglio:

  • Impostare la richiamata per i vostri eventi dei pulsanti, in modo che in realtà fa qualcosa quando si fa clic.

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

EDIT: codice rettificato per l'utilizzo di un pulsante del sistema, che rende un sacco di quello che avevo scritto uneccessary.

+0

Nel suo codice di esempio, non è necessario rilasciare il pulsante, perché [Pulsante UIButtonWithType:] restituisce un'istanza autorizzata. –

+0

Hai esattamente ragione, l'ho copiato dal codice * I * avevo dove usavo il mio initWithFrame. Regolazione. – mmc

+0

Grazie per il feedback. È stato notato il suggerimento con rilascio/autorelease. È davvero necessario armeggiare con il telaio? Voglio semplicemente che il pulsante riempia l'intera cella della tabella (non si preoccupi della posizione e della dimensione); "Elimina evento" lo dimostra bene. –

1

Sì, sei sulla strada giusta, questo è il modo più semplice per aggiungere una sottoview a una cella (l'altra è una sottoclasse di UITableViewCell).

Controllare lo Apple guide per ulteriori informazioni.

19

Il modo in cui lo hai ora ogni volta che viene visualizzata una cella stai assegnando un pulsante, impostandone il valore e aggiungendolo al contentView della cella. Quando la cella viene riutilizzata (tramite dequeueReusableCellWithIdentifier) verrà creato un altro pulsante nuovo, aggiungendolo alla cella (sopra a quello vecchio) ecc. Il fatto che sia passato attraverso addSubview ma nessun rilascio esplicito significa che ogni pulsante mantiene il conteggio non andrà mai a zero, quindi resteranno tutti intorno. Dopo un po 'di scorrere verso l'alto e verso il basso la cella finirà con centinaia di sottoview dei pulsanti che probabilmente non sono ciò che desideri.

Alcuni consigli:

  • non allocano mai roba dentro una chiamata cellForRowAtIndexPath a meno che non si fa quando dequeueReusableCellWithIdentifier sta tornando a zero e il gioco è l'inizializzazione della cella. Tutte le altre volte successive ti verrà restituita la cella memorizzata nella cache che avrai già impostato in modo che tutto ciò che devi fare sia modificare le etichette o le icone. Dovrai spostare tutte le voci di assegnazione dei pulsanti all'interno del condizionale if subito dopo il codice di allocazione delle celle.

  • Il pulsante deve avere una posizione e anche un obiettivo impostato in modo che esegua qualcosa quando viene toccato. Se ogni cella avrà questo pulsante, un trucco è quello di farli puntare tutti allo stesso metodo di destinazione, ma impostare il valore tag del pulsante su indexPath.row della cella (all'esterno del blocco di allocazione della cella poiché varia per ogni cella). Il gestore di tocco comune per il pulsante utilizza il valore del tag del mittente per cercare i dati sottostanti nell'elenco DataSource.

  • Chiama il release sul pulsante dopo aver eseguito uno addSubview. In questo modo il conteggio dei ritiri cadrà a zero e l'oggetto verrà effettivamente rilasciato quando viene rilasciato il genitore.

  • Invece di aggiungere il pulsante tramite addSubview, è possibile restituire il accessoryView per la cella in modo da non dovete preoccuparvi di posizionandolo (a meno che non si sta già utilizzando l'accessoryView per qualcos'altro - divulgazione come pulsanti).

+1

Grazie mille per i preziosi suggerimenti e spiegazioni. Un principiante di programmazione per iPhone come me ne è certo apprezzato. Per quanto riguarda la punta 4, come con "Elimina evento"/"Condividi Contatta" Dovrò solo un pulsante nella parte inferiore dell'interfaccia utente cioè in ultima fila. Quindi, non può essere l'accessorioView, ma deve riempire l'intera riga. Sto ancora lottando con quello. –

+2

Per quanto riguarda il n. 3, il rilascio del pulsante causerà il crash dell'applicazione. Non lo sta distribuendo. – DougW

+0

Nizza scrivi Ramin! – Jordan

7

Ho scelto un approccio diverso per creare un equivalente al pulsante "Elimina evento" nell'app Calendario. Invece di aggiungere un pulsante come sottoview, ho aggiunto due sfondi (rosso e rosso più scuro, con gradazioni gradevoli) alle celle, quindi arrotondato gli angoli e impostato il bordo in grigio.

Il seguente codice crea una cella riutilizzabile (nel modo usuale). Le due immagini a cui si fa riferimento ('redUp.png' e 'redDown.png') sono state prese da uno screenshot del pulsante 'Delete Event' del calendario. (Sembrava più veloce di creare i gradienti a livello di programmazione.) C'è spazio per un po 'più di messa a punto per avvicinarsi ancora di più all'aspetto' Cancella evento 'del calendario, ma questo è molto vicino.

azione del pulsante viene attivato dal tableView metodo delegato tableView: didSelectRowAtIndexPath: metodo.

// 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

Dovresti aggiungere '[cell.textLabel setShadowColor: [UIColor blackColor]]; [cell.textLabel setShadowOffset: CGSizeMake (0, -1)], 'al codice. Ciò conferisce al testo un effetto leggermente in rilievo in modo che assomigli più al pulsante nativo. – Greg