Abbiamo visto come il componente TabNavigator offra un metodo semplice ma al tempo stesso piuttosto versatile per creare dei sistemi di navigazione "a schede" con buone possibilità di personalizzazione sia per quanto riguarda le intestazioni, sia per quanto concerne la disposizione dei contenuti di ogni scheda.
Flex mette a disposizione un altro componente che consente di avere praticamente le stesse funzioni viste con il TabNavigator, con in più però l'opportunità di mantenere separata la parte con le intestazioni dalla parte visuale: si tratta del componente TabBar, che in cooperazione col componente Viewstacker permette di ottenere comportamenti uguali o simili a quelli visti con il TabNavigator, lasciando però maggiori libertà per il layout data la separazione tra le due componenti.
Il componente TabBar
Avviamo un nuovo Flex Project, quindi portiamoci nella visuale Design per avere accesso ai componenti. Dal pannello components selezioniamo la categoria Navigators, quindi il componente TabBare trasciniamone un'istanza sull'area di lavoro.
Una volta posizionato sullo stage, notiamo come il componente TabBar risulti rappresentato come un rettangolo trasparente con solo il bordo bianco, senza alcuna tab (differentemente da quanto avveniva con il TabNavigator che presentava invece già una tab presente); quando il componente è selezionato possiamo vedere i tasti "+" e "-" per l'aggiunta e la rimozione di voci dal menu.
Aggiungere nuove voci
Potremmo pensare che per aggiungere una nuova voce basti selezionare il componente e premere il pulsante + come per il componente TabNavigator: se proviamo a farlo otteniamo però il seguente errore.
Cosa significa? Semplicemente Flex ci informa che per poter inserire una nuova voce all'interno della TabBar è necessario avere a disposizione sullo stage almeno un'istanza del componente ViewStack, che di fatto costituirà l'area di visualizzazione delle schede. La mancanza di tale componente impedirebbe il funzionamento della TabBar, quindi non possiamo aggiungere voci senza prima inserire un ViewStack sullo stage; portiamoci allora nuovamente nel pannello Componenti, selezioniamo il componente ViewStack (anch'esso presente nella categoria Navigators) e posizioniamolo a piacere sullo stage. Possiamo decidere di assegnare un id
al componente dal pannello proprietà oppure lasciare che sia Flex ad assegnarli un id predefinito.
Il componente, una volta posizionato sullo stage, appare in maniera analoga alla TabBar, ovvero un rettangolo con bordo bianco; quando selezionato mostra i pulsanti "+" e "-" e due frecce, una a sinistra e una a destra.
Dopo aver inserito il componente ViewStack, se proviamo nuovamente ad aggiungere una voce al TabBar apparirà il pannello illustrato in figura.
Le opzioni inerenti New view label
e View type
sono le stesse già viste per il TabNavigator: la prima imposta l'etichetta usata dal TabBar mentre la seconda imposta il tipo di contenitore che verrà usato per la visuale corrispondente nel ViewStack. In questo caso, essendo intestazione e parte visuale separate, dovremo scegliere dalla combo ViewStackID quale sia il componente che mostrerà le varie schede.
Attenzione: non è possibile associare alcune tabelle a un viewstack e alcune a un altro. Ovviamente potremo utilizzare ad esempio due TabBar e due ViewStack, ma l'associazione tra essi deve essere univoca e quindi a ogni TabBar potrà corrispondere solamente un ViewStack.
Aggiungere oggetti ad una scheda
Una volta create una o più visuali potremo andare ad inserire i rispettivi oggetti nel componente ViewStack: nella modalità di design possiamo cliccare sulle intestazioni della TabBar per spostarci tra le visuali corrispondenti, quindi usare il drag & drop per inserire gli oggetti nel ViewStack.
In modalità codice avremo una situazione di questo tipo:
<mx:TabBar x="10" y="19" dataProvider="viewstack1">
</mx:TabBar>
<mx:ViewStack x="172" y="178" id="viewstack1" width="200" height="200">
<mx:Canvas label="Scheda uno" width="100%" height="100%">
<mx:Button x="10" y="10" label="Button"/>
</mx:Canvas>
<mx:VDividedBox label="Scheda due">
<mx:HSlider/>
<mx:DateField height="80"/>
</mx:VDividedBox>
</mx:ViewStack>
Ovviamente trattandosi di due componenti separati abbiamo una maggior divisione: possiamo notare come il componente TabBar di fatto abbia come proprietà (oltre alle dimensioni) soltanto dataProvider: questo perchè le informazioni sulle etichette da mostrare le ricava dal componente ViewStack.
Tale componente è codificato come un tag che contiene a sua volta diversi sottotag (corripsondenti alle varie visuali), nel nostro esempio <mx:Canvas> e <mx:VDividedBox>, che a loro volta includono poi i vari oggetti (la prima scheda presenta solo un bottone, la seconda un componente HSlider e un DateField).
Con il codice visto sopra, la situazione in visuale Design sarà di questo tipo:
TabBar con due schede
Modificare le proprietà dei contenitori
La modifica per le proprietà dei vari contenitori funziona esattamente come nel componente TabNavigator, basterà selezionare il contenitore desiderato dal componente ViewStack e applicare le modifiche.
Inserire un'icona nelle intestazioni
Anche per l'inserimento di icone nelle intestazioni possiamo utilizzare lo stesso metodo visto per il TabNavigator: basterà operare sui tag dei contenitori presenti nel ViewStack, in questo modo:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="400" height="400" >
<mx:TabBar x="10" y="19" dataProvider="viewstack1">
</mx:TabBar>
<mx:ViewStack x="172" y="178" id="viewstack1" width="200" height="200">
<mx:Canvas label="Scheda uno" icon="@Embed('icona.png')"
width="100%" height="100%" backgroundColor="#FFFFFF">
<mx:Button x="10" y="10" label="Button"/>
</mx:Canvas>
<mx:VDividedBox label="Scheda due">
<mx:HSlider/>
<mx:DateField height="80"/>
</mx:VDividedBox>
</mx:ViewStack>
</mx:Application>
Situazione con dueschede, di cui la prima provvista di icona
Un aspetto per cui dobbiamo cambiare leggermente rispetto al TabNavigator è l'allineamento delle etichette rispetto all'icona: anche in questo caso bisogna utilizzare Actionscript, ma il codice varia rispetto a quanto visto con il TabNavigator.
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="400" height="400" backgroundColor="white">
<mx:Script>
<![CDATA[
private function init():void {
import mx.controls.tabBarClasses.Tab
var len:uint = tab_bar.numChildren;
for (var t:uint=0; t<len; t++) {
var tab:Tab = tab_bar.getChildAt(t) as Tab
tab.labelPlacement = tab.label;
}
}
]]>
</mx:Script>
<mx:TabBar x="10" y="19" id="tab_bar" dataProvider="viewstack1" creationComplete="init()">
</mx:TabBar>
<mx:ViewStack x="172" y="178" id="viewstack1" width="200" height="200">
<mx:Canvas label="left" icon="@Embed('icona.png')" width="100%" height="100%">
</mx:Canvas>
<mx:Canvas label="right" icon="@Embed('icona.png')" width="100%" height="100%">
</mx:Canvas>
<mx:Canvas label="top" icon="@Embed('icona.png')" width="100%" height="100%">
</mx:Canvas>
<mx:Canvas label="bottom" icon="@Embed('icona.png')" width="100%" height="100%">
</mx:Canvas>
</mx:ViewStack>
</mx:Application>
Molto semplicemente la differenza è che in questo caso utilizziamo direttamente il metodo getChildAt, mentre per il TabNavigator avevamo dovuto usare getTabAt.
Con questo codice, una volta completata la creazione del componente (creationComplete) richiamiamo la funzione init, che va a ricavare le tab del componente (getChildAt(t) all'interno del ciclo) e ne imposta l'allineamento dell'etichetta in base al valore dell'etichetta stessa (notiamo che come nomi abbiamo usato left, right, top e bottom ovvero i possibili valori di allineamento).
TabBar con differenti allineamenti per le etichette
Dare diversi stili alle intestazioni
Un'altra possibilità molto interessante che possiamo sfruttare partendo dallo script appena visto è l'associazione di diversi stili alle intestazioni, ovvero l'assegnazione di diverse proprietà ad ognuno dei tab; questo permette di cambiare ad esempio il colore di sfondo di ogni tab della TabBar; basterà modificare la funzione init come di seguito.
<mx:Script>
<![CDATA[
private function init():void {
import mx.controls.tabBarClasses.Tab
var colori:Array = ["red", "haloOrange", "yellow", "haloGreen", "haloBlue"];
var len:uint = tab_bar.numChildren;
for (var t:uint=0; t<len; t++) {
var tab:Tab = tab_bar.getChildAt(t) as Tab
tab.labelPlacement = tab.label;
tab.setStyle("fillColors",[colori[t],"white"])
}
}
]]>
</mx:Script>
Notiamo nell'esempio come ogni tab, quando non selezionata, ha un suo colore specifico.
TabBar con differenti colori
Ruotare la TabBar
Avere separate le intestazioni dall'area di visualizzazione ci permette di creare effetti e situazioni più o meno "particolari", per esempio potremmo voler ruotare la TabBar (ad esempio per metterla in verticale accanto all'area di visualizzazione); per questo possiamo utilizzare la proprietà rotation, ma sarà indispensabile prima includere i font nelle label, altrimenti dopo la rotazione queste non risulterebbero visibili.
Per questo possiamo sfruttare i tag <mx:Style>, ad esempio con il seguente codice viene incluso nel file un font non di sistema (Newtown)
<mx:Style>
@font-face{
src:locale("Newtown");
fontFamily: Newtown;
fontWeight:bold
}
</mx:Style>
Il parametro fontFamily che abbiamo specificato indica con quale stringa dovremo farvi riferimento dalla proprietà fontFamily dell'oggetto TabBar:
<mx:TabBar fontFamily="Newtown" rotation="90" x="172" y="27" id="tab_bar" dataProvider="viewstack1" creationComplete="init()">
Di seguito due risultati di TabBar ruotate rispetivamente di 30 e 90 gradi.
TabBar con differenti colori
TabBar con differenti colori
Possiamo quindi concludere dicendo che i componenti TabNavigator e TabBar seppur molto simili risultano anche abbastanza nettamente divisi: per l'uso più "classico", ovvero con le instazioni subito sopra l'area di visualizzazione, il TabNavigator è più rapido da utilizzare, ma se vogliamo una maggior libertà per il nostro layout, magari per creare qualche effetto "particolare", il componente TabBar risulta decisamente più efficace.