Continuiamo il nostro tour dell’UIkit framework analizzando oggi la classe UIButton.

Come sempre, la guida di riferimento è la Class Reference pubblicata da Apple® che potete trovare a questo indirizzo.

Analizzando la Class Reference, l’informazione principale, e non a caso Apple® la inserisce per prima, è l’albero “genealogico” della classe in questione, per esempio per la classe UIButton la reference dice:

inherits from UIControl : UIView : UIResponder : NSObject

quindi la gerarchia è questa:


Gerarchia della classe UIButton


Ho segnato in verde le classi che abbiamo già trattato su questo sito, in rosso la classe che trattiamo oggi.

Come è facile intuire, più ci spostiamo verso il basso nella gerarchia delle classi, più saranno i metodi e le proprietà utilizzabili sulla classe stessa, questo perché non solo dobbiamo considerare metodi e proprietà proprietari della classe, ma anche tutti quelli delle sue superclassi ereditati.

Credo che tutti sappiano trascinare un UIButton da Interface Builder, vediamo invece come aggiungerne uno alle nostre view a runtime

[UIButton * btn = [UIButton buttonWithType:UIButtonTypeRoundedRect];btn.frame = CGRectMake(0, 0, 100, 50);
[btn setTitle:@"Hello, world!" forState:UIControlStateNormal];
[self.view addSubview:btn];

Esaminando il codice vediamo subito un particolare costruttore che prende in input un (UIButtonType)buttonType; questo può avere 6 possibili diversi valori ed il risultato è quello che si vede in questa immagine.


UIButtonType


Nella prima riga non c’è un errore, il pulsante non si vede perché è un rettangolo trasparente. Questo tipo di pulsante può essere comodamente usato per ottenere un pulsante personalizzato, (se si chiama “custom” ci sarà un perché) infatti basterà inserire sotto il pulsante un controllo UIImageView di dimensioni e contenuto appropriato per ottenere un pulsante con qualsiasi immagine.

Per i fans di Interface Builder lo stesso risultato è ottenibile selezionando la voce corrente nel menù a discesa presente in “attributes inspector”:


UibuttonType su Interface Builder

UIButtonType in interface builder


Nell’istruzione successiva ne impostiamo la dimensione e posizione tramite la funzione CGRectMake già vista nell’articolo sulle UILabel.

Gli oggetti della classe derivate da UIControl  possono trovarsi in diversi stati (anche più contemporaneamente). Gli stati possibili sono:

UIControlStateNormal il controllo è attivo
UIControlStateHighlighted È lo stato “evidenziato” dei controlli. Un controllo si trova in questo stato quando viene toccato o quando viene trascinato. Possiamo verificare via codice se un controllo si trova in questo stato esaminando la sua proprietà ishighlighted
UIControlStateDisabled Il controllo è disabilitato.
UIControlStateSelected Stato “selezionato”. per molti controlli non è disponibile.
UIControlStateApplication Riservato per scopi interni alla nostra applicazione.
UIControlStateReserved Riservato per scopi riservati del framework.

Tutti i metodi che servono per modificare l’aspetto estetico dei controlli prendono quindi come parametro anche uno di questi valori. Sarà quindi possibile realizzare per esempio un pulsante rosso che diventa grigio quando viene disattivato e verde quando viene cliccato.

I metodi per modificare l’aspetto dei pulsanti sono:

- (void)setTitle:(NSString *)title forState:(UIControlState)state
- (void)setTitleColor:(UIColor *)color forState:(UIControlState)state
- (void)setTitleShadowColor:(UIColor *)color forState:(UIControlState)state
- (void)setImage:(UIImage *)image forState:(UIControlState)state
- (void)setBackgroundImage:(UIImage *)image forState:(UIControlState)state="objc"

Per ricevere in lettura questi valori sono previsti metodi analoghi:

- (NSString *)titleForState:(UIControlState)state
- (UIColor *)titleColorForState:(UIControlState)state
- (UIColor *)titleShadowColorForState:(UIControlState)state
- (UIImage *)imageForState:(UIControlState)state
- (UIImage *)backgroundImageForState:(UIControlState)state

Come se non bastasse sono state previste anche delle proprietà che quindi vengono usate con la sintassi nome_oggetto.nomeproprietà:

@property(nonatomic,readonly,retain) UILabel *titleLabel
@property(nonatomic, readonly, retain) NSString *currentTitle
@property(nonatomic, readonly, retain) UIColor *currentTitleColor
@property(nonatomic, readonly, retain) UIColor *currentTitleShadowColor
@property(nonatomic, readonly, retain) UIImage *currentImage
@property(nonatomic, readonly, retain) UIImage *currentBackgroundImage

Tutte queste personalizzazioni possono essere specificate anche tramite interface builder, ma se vogliamo modificare le proprietà di un controllo a runtime l’unica possibilità che abbiamo è quella di adoperare i metodi forniti da apple.


Proprietà di UIButtton da interface builder


Vediamo qualche esempio di utilizzo di questi metodi:

//Creo un oggetto UIButton di tipo TypeRoundedRect
UIButton * btn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
//lo posiziono al centro schermo.
btn.frame = CGRectMake(35, 215, 250, 50);
//ne imposto ìl titolo per lo stato normale.
[btn setTitle:@"STATO: NORMALE" forState:UIControlStateNormal];
//ne imposto il colore del titolo per lo stato normal.
[btn setTitleColor:[UIColor greenColor] forState:UIControlStateNormal];
//ne imposto il titolo per lo stato "cliccato"
[btn setTitle:@"STATO: CLICCATO" forState:UIControlStateHighlighted];
//ne imposto il colore del titolo per lo stato "cliccato"
[btn setTitleColor:[UIColor redColor] forState:UIControlStateHighlighted];
//accedo alla proprietà currentTitle
NSLog(@"IN QUESTO MOMENTO HA TITOLO: %@", btn.currentTitle);
//accedo al valore del titolo allo stato "cliccato."
NSLog(@"NELLO STATO ATTIVO HA TITOLO: %@",[btn titleForState:UIControlStateHighlighted]);

Prima di concludere vediamo due ultime “chicche”: la prima è la proprietà showsTouchWhenHighlighted, che determina se il pulsante deve illuminarsi quando viene cliccato. Basta quindi scrivere btn.showsTouchWhenHighlighted = YES un’ottima animazione sui nostri pulsanti.
Con la seconda ed ultima chicca vediamo la possibilità di assegnare, sempre a runtime, una funzione ad un determinato evento sul controllo (per i più smaliziati..una sorta di binding dinamico).

Il metodo è il seguente:

- (void)addTarget:(id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents

“target” è l’oggetto che deve rispondere all’evento..di solito si utilizza “self”

“action” è un selector, ne parleremo magari più avanti, per il momento basti dire che è il nome di un metodo dichiarato nella nostra classe.

“controlEvents” è l’evento che che deve essere riconosciuto.

nel nostro caso potremmo quindi scrivere

[btn addTarget:self action:@selector(aMethod:) forControlEvents:UIControlEventTouchDown];

@lla prossima :)