Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

Utilizzare gli stati in Flex 3

Flex permette di impostare diversi stati della propria applicazione e inserire facilmente degli effetti di transizione tra uno stato e l'altro usando i comandi MXML. Nell'articolo vediamo come fare con semplici esempi
Flex permette di impostare diversi stati della propria applicazione e inserire facilmente degli effetti di transizione tra uno stato e l'altro usando i comandi MXML. Nell'articolo vediamo come fare con semplici esempi
Link copiato negli appunti

Un'interessante caratteristica di Flex è la possibilità di impostare diversi "stati" della propria applicazione e inserire facilmente degli effetti di transizione tra uno stato e l'altro usando i comandi MXML. Possiamo considerare gli stati (states) di un'applicazione come dei cambiamenti nella disposizione dei suoi elementi, pensiamo ad esempio agli spazi di lavoro (workspaces) offerti da diverse applicazioni professionali dove a seconda delle proprie esigenze l'utente può optare per una precisa disposizione dei pannelli. Non ci riferiamo quindi alla semplice apertura di un pannello, ma a cambi di visualizzazione che coinvolgano più elementi.

In questo articolo vedremo come impostare diversi stati per un'applicazione, come passare da uno all'altro e come inserire degli effetti per rendere meno brusco e più accattivante lo spostamento tra una disposizione e l'altra; tutto questo è realizzabile in maniera molto semplice in Flex utilizzando precisi comandi MXML.

Impostazione del filmato

Per prima cosa andiamo a vedere come sia possibile inserire diversi stati per la nostra applicazione. Per prima cosa avviamo un nuovo progetto Flex (File -> New -> Flex Project), diamogli un nome a piacere e, una volta impostato Web Application come Application Type e None come Server Technology, premiamo il pulsante Finish.

Figura 1. Finestra di creazione di un nuovo progetto
Screenshot del pannello

A questo punto Flex ci mostrerà il nostro file aperto; portiamoci nella visuale Design e vedremo il nostro file ancora vuoto; notiamo in alto a destra il pannello States. Qualora questo pannello non risultasse aperto apriamo il menù Window e clicchiamo sulla voce States per farlo comparire.

Figura 2. Il pannello "States"
Screenshot del pannello

Come possiamo vedere lo stato impostato di default si chiama Base state ed è impostato come stato iniziale dell'applicazione (start). Possiamo facilmente intuire che qualsiasi elemento andremo a posizionare sullo stage farà parte di tale stato e sarà visibile all'avvio dell'applicazione trovandosi nello stato impostato come iniziale. Posizioniamo quindi alcuni elementi sullo stage, ad esempio potremmo disporre tre componenti di tipo Panel. L'importante sarà assegnare ad ognuno un ID diverso (nell'esempio pnl1, pnl2 e pnl3) e un titolo per identificarlo facilmente.

Inseriamo infine un pulsante che utilizzeremo per passare agli altri stati.

Figura 3. Gli elementi disposti sullo stage
Screenshot dello stage

L'ID assegnato ai pannelli è molto importante poiché lo utilizzeremo in seguito, quando assoceremo gli effetti ai campi di stato; tale parametro si può impostare dal pannello Flex Properties e in figura è possibile vedere le proprietà del pannello 3.

Figura 4. Proprietà di "Pannello 3"
Screenshot del pannello

Creazione di nuovi stati

A questo punto abbiamo disposto tre elementi sullo stage e un pulsante che utilizzeremo per il cambio di stato; i tre pannelli che nello stato base hanno la stessa dimensione assumeranno un diverso aspetto negli stati che andremo ora a creare.

Per prima cosa portiamoci nel pannello States e premiamo l'icona New state, l'unica inizialmente attiva nel pannello; una volta premuta l'icona si aprirà un nuovo pannello che richiederà l'inserimento del nome dello stato da creare, lo stato da cui partire e la possibilità di impostarlo come stato iniziale. Inizialmente l'opzione Based on avrà come unico valore Base State, visto che è l'unico stato presente nel progetto.

Figura 5. Il pannello "New State"
Screenshot del pannello

L'opzione Based on è molto utile poiché ci permette di stabilire da quale situazione vogliamo partire per creare il nuovo stato; vedremo meglio in seguito questo aspetto.

Una volta premuto il tasto OK il pannello States mostrerà il nuovo stato, che risulterà collegato al Base State e presenterà la medesima situazione sullo stage.

Figura 6. Il pannello "States" dopo la creazione del nuovo stato
Screenshot del pannello

Notiamo che per Stato2 sono attive anche le icone per la modifica e l'eliminazione dello stato. Mantenendo Stato2 selezionato nel pannello States, modifichiamo gli elementi presenti nello stage andando a cambiarne, per esempio, la dimensione e la posizione. In ogni momento potremo cliccare su Base State dal pannello States e noteremo così come, mentre Stato2 manterrà le modifiche eseguite agli oggetti, Base State rimarrà invariato.

In figura possiamo vedere una delle possibili variazioni per Stato2.

Figura 7. Lo stato "Stato2" con i pannelli modificati
Screenshot dello stage

Passare da uno stato all'altro

Prima di vedere come creare nuovi stati e di trattare l'aggiunta e rimozione degli elementi vediamo come passare da Base State a Stato2 e viceversa.

Un aspetto molto interessante è che nei vari stati non solo possiamo variare l'aspetto grafico degli elementi, ma anche le loro azioni: utilizzeremo infatti sempre il medesimo pulsante Cambia ordine per i due passaggi di stato.

Il comando per cambiare stato in Flex è currentState='nomestato'. Andiamo allora nello stato Base State, selezioniamo il pulsante "Cambia ordine" e impostiamo come azione onClick dal pannello Flex Properties l'azione currentState='Stato2'. In alternativa potremmo portarci nel codice MXML (quindi nella visuale Source) e cambiare il codice del pulsante in questo modo

<mx:Button x="391" y="345" label="Cambia ordine" click="currentState='Stato2'" />

Andiamo ora ad eseguire la stessa operazione per il pulsante in Stato2: selezioniamo Stato2 dal pannello States, quindi clicchiamo sul pulsante "Cambia ordine" nello stage e come azione onClick impostiamo currentState=''. Qualora volessimo impostare la proprietà dal codice MXML dovremo operare in maniera diversa da quanto fatto per il pulsante precedente; gli stati vengono infatti indicati nel codice MXML all'interno dei tag <mx:states> ed è necessario dichiarare solamente le proprietà da cambiare. Possiamo facilmente riscontrarlo portandoci nella visualizzazione Source dove il codice sarà simile al seguente:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
  <mx:states>
    <mx:State name="Stato2">
      <mx:SetProperty target="{pnl1}" name="height" value="88"/>
      <mx:SetProperty target="{pnl2}" name="height" value="324"/>
      <mx:SetProperty target="{pnl2}" name="y" value="125"/>
      <mx:SetProperty target="{pnl3}" name="height" value="88"/>
      <mx:SetProperty target="{pnl3}" name="x" value="308"/>
      <mx:SetProperty target="{pnl3}" name="y" value="125"/>
      <mx:SetProperty target="{pnl1}" name="width" value="522"/>
    </mx:State>
  </mx:states>
  <mx:Panel x="36" y="29" layout="absolute" title="Pannello 1" id="pnl1">
  </mx:Panel>
  <mx:Panel x="36" y="249" layout="absolute" title="Pannello 2" id="pnl2">
  </mx:Panel>
  <mx:Panel x="310" y="29" layout="absolute" id="pnl3" title="Pannello 3">
  </mx:Panel>
  <mx:Button x="391" y="345" label="Cambia ordine" click="currentState='Stato2'" id="button1"/>
</mx:Application>

Notiamo le proprietà impostate in Stato2, racchiuse tra i tag <mx:State>. Possiamo anche vedere che la proprietà target per le varie azioni fa riferimento all'identificavo degli oggetti, ed ecco perché era importante impostare un ID per i pannelli quando li abbiamo creati.

Per variare il comportamento del nostro pulsante (che ha come id "button1") sarà necessario aggiungere questa riga di codice all'interno dei tag <mx:State> relativi a Stato2.

<mx:SetEventHandler target="{button1}" name="click" handler="currentState=''"/>

Possiamo ora testare il filmato e premiamo il pulsante "Cambia ordine": noteremo come il passaggio da Base State a Stato2 sia perfettamente funzionante (come nell'esempio seguente).

Esempio di passaggio tra gli stati

Utilizzo delle transizioni

Il passaggio tra i due stati avviene correttamente, ma potrebbe essere interessante renderlo più graduale, magari mostrando lo spostamento di Pannello 3 e il ridimensionamento dei tre pannelli, realizzando l'animazione tra i due stati.

Con Flex questo è molto semplice grazie alle transizioni, che permettono con pochi tag di dare al player le istruzioni sulle animazioni che verranno poi generate.

Per realizzare una transizione è necessario usare il codice MXML, portiamoci quindi nella visuale Source. Ogni transizione va inclusa nei tag <mx:transitions>; tali tag, proprio come gli stati, possono contenere una o più transizioni e ognuna di esse sarà inclusa nei tag <mx:Transition>. Nel nostro esempio utilizzeremo una sola transizione, impostiamo quindi il codice in questo modo:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">

<mx:transitions>
<mx:Transition>

</mx:Transition>
</mx:transitions>

<mx:states>
  <mx:State name="Stato2">
    <mx:SetProperty target="{pnl1}" name="height" value="88"/>
    <mx:SetProperty target="{pnl2}" name="height" value="324"/>
    <mx:SetProperty target="{pnl2}" name="y" value="125"/>
    <mx:SetProperty target="{pnl3}" name="height" value="88"/>
    <mx:SetProperty target="{pnl3}" name="x" value="308"/>
    <mx:SetProperty target="{pnl3}" name="y" value="125"/>
    <mx:SetProperty target="{pnl1}" name="width" value="522"/>
    <mx:SetEventHandler target="{button1}" name="click" handler="currentState=''"/>
  </mx:State>
</mx:states>
<mx:Panel x="36" y="29" layout="absolute" title="Pannello 1" id="pnl1"></mx:Panel>
<mx:Panel x="36" y="249" layout="absolute" title="Pannello 2" id="pnl2"></mx:Panel>
<mx:Panel x="310" y="29" layout="absolute" id="pnl3" title="Pannello 3"></mx:Panel>
<mx:Button x="391" y="345" label="Cambia ordine" click="currentState='Stato2'" id="button1"/></mx:Application>

Ogni transizione può contenere diversi effetti, che possono essere eseguiti simultaneamente (Parallel) o in sequenza (Sequence); ogni effetto deve recare specificati gli elementi che coinvolge (target). Flex mette a disposizione effetti di movimento (Move), ridimensionamento (Resize), transizione (Fade), rotazione (Rotate) e molti altri ancora; ogni effetto ha il suo specifico tag. Per ora ci limiteremo all'uso dell'effetto Move per il pannello 3 (con id pnl3) e al resize per tutti e 3 i pannelli (pnl1, pnl2, pnl3). Eseguiremo gli effetti simultaneamente, usando quindi il tag Parallel. Ecco il codice:

<mx:transitions>
  <mx:Transition>
    <mx:Parallel>
      <mx:Move target="{pnl3}" />
      <mx:Resize targets="{[pnl1,pnl2,pnl3]}" />
    </mx:Parallel>
  </mx:Transition>
</mx:transitions>

Notiamo l'uso della proprietà target per l'effetto Move che coinvolge un solo elemento, mentre per l'effetto Resize abbiamo usato targets che è un parametro di tipo Array e contiene gli id di tutti gli oggetti coinvolti dall'effetto.

Non avendo specificato alcun parametro per la transizione, l'effetto verrà eseguito in qualsiasi passaggio di stato e quindi sia da Base State a Stato2 che da Stato2 a Base State, come è anche possibile vedere nell'esempio che segue.

Esempio di passaggio tra gli stati con applicata una transizione

Ogni transizione permette di impostare le proprietà fromState e toState, relative rispettivamente allo stato iniziale e a quello finale: tramite queste due proprietà è molto semplice fare in modo che una transizione venga eseguita solo in particolari occasioni, per esempio se volessimo visualizzare l'effetto nel passaggio da Base State a Stato2, ma non per il percorso inverso, basterà modificare in questo modo il nostro codice:

<mx:transitions>
  <mx:Transition fromState="" toState="Stato2">
    <mx:Parallel>
      <mx:Move target="{pnl3}" />
      <mx:Resize targets="{[pnl1,pnl2,pnl3]}" />
    </mx:Parallel>
  </mx:Transition>
</mx:transitions>

È facile intuire che sfruttando tali proprietà possiamo creare una diversa transizione per il passaggio da Stato2 a Base State, supponiamo per esempio di voler applicare a pnl1 un effetto Resize e un effetto Blur, senza agire sugli altri elementi; basterà creare una nuova transizione contenente questi due effetti ed esclusiva per il passaggio di stati che ci interessa, in questo modo:

<mx:transitions>
  <mx:Transition fromState="" toState="Stato2">
    <mx:Parallel>
      <mx:Move target="{pnl3}" />
      <mx:Resize targets="{[pnl1,pnl2,pnl3]}" />
    </mx:Parallel>
  </mx:Transition>
  <mx:Transition fromState="Stato2" toState="">
    <mx:Parallel>
      <mx:Resize target="{pnl1}" />
      <mx:Blur blurXFrom="50" blurXTo="0" target="{pnl1}" />
    </mx:Parallel>
  </mx:Transition>
</mx:transitions>

Vi sono molti altri possibili effetti utilizzabili con Flex, ma non li tratteremo ora poiché questo articolo è relativo principalmente all'uso degli stati.

Aggiungere o rimuovere elementi

Finora abbiamo visto come agire quando tra lo stato iniziale e quello finale cambia solo la dimensione o la disposizione degli elementi: ma cosa succederebbe se volessimo aggiungere o rimuovere degli oggetti?

Andiamo a creare un nuovo stato, chiamiamolo Stato3 e basiamolo su Stato2; noteremo come nel pannello States Stato3 risulterà subordinato a Stato2.

Tale subordinazione si traduce principalmente nel fatto che qualora eliminassimo Stato2, anche Stato3 verrà rimosso.

Figura 8. Lo "Stato3" risulta collegato e subordinato a "Stato2"
Screenshot del pannello

Stato3 risulterà inizialmente uguale a Stato2: andiamo a modificarla inserendo un nuovo pannello (con ID pnl4) e un nuovo pulsante (con ID button2) e sostituendo Pannello 2 con una finestra (con ID fin1). La situazione sarà simile a quella in figura; button1 permetterà di tornare allo stato base, mentre button2 collegherà a Stato2.

Figura 9. Lo stato "Stato3" dopo le modifiche
Screenshot dello stage

Dobbiamo ovviamente rendere raggiungibile Stato3, ma poiché ci interessa solo a scopo didattico andiamo semplicemente a cambiare l'azione di button1 nello stato base, collegandolo a Stato3 invece che a Stato2.

Testando il filmato non noteremmo nessun problema: i due stati variano correttamente e non c'è alcuna transizione tra di essi (infatti le transizioni sono state impostate per agire solo nei passaggi con coinvolto Stato2); cosa succederebbe però se impostassimo una transizione dallo stato base a Stato3?

Come possiamo vedere nell'esempio seguente, i nuovi elementi vengono aggiunti immediatamente.

Esempio di passaggio tra gli stati con creazione e sostituzione di oggetti

Certo non possiamo definirlo completamente un problema, ma potremmo voler rendere più graduale la sostituzione di un elemento facendo per esempio scomparire gradualmente pnl2 e sostituendolo solo in seguito con fin1. Per questo scopo risultano fondamentali sia le transizioni in sequenza, sia i comandi <mx:RemoveChildAction /> e <mx:AddchildAction /> che permettono di controllare rispettivamente la rimozione e l'inserimento di uno o più elementi.

Prendiamo ad esempio il seguente codice:

<mx:transitions>
  <mx:Transition fromState="" toState="Stato3">
    <mx:Sequence targets="{[pnl1,pnl2,fin1]}">
      <mx:Parallel>
        <mx:Resize target="{pnl1}" />
        <mx:Fade alphaTo="0" target="{pnl2}" />
        <mx:Blur blurXFrom="50" blurXTo="0" target="{pnl1}" />
      </mx:Parallel>
      <mx:RemoveChildAction />
      <mx:AddChildAction />
      <mx:Fade alphaFrom="0" alphaTo="1" target="{fin1}" />
    </mx:Sequence>
  </mx:Transition>
</mx:transitions>

La transizione viene impostata da Base state a Stato3 e viene impostata una sequenza che agirà su pnl1, pnl2 e fin1. Per prima cosa vengono eseguiti in contemporanea (grazie a <mx:Parallel>) gli effetti Blur e Resize su pnl1 e l'effetto Fade (con trasparenza finale uguale a 0) su pnl2. Una volta conclusi questi tre effetti vengono rimossi gli elementi che vanno eliminati dallo stage (nel nostro caso pnl2) e verrà aggiunto invece fin1, che avrà anche un entrata in dissolvenza con trasparenza da 0 ad 1. Ecco il risultato:

Esempio di passaggio tra gli stati con creazione e sostituzione di oggetti e applicata una transizione

Notiamo che pnl4 e button2 appaiono immediatamente e non sono coinvolti dalla transizione: questo perché non sono stati inseriti tra i targets nel tag <mx:Sequence>, per cui funzionano come se la transizione non fosse presente; se volessimo far apparire anche questi due elementi soltanto dopo la scomparsa di pnl2 dovremmo modificare il nostro codice in questo modo:

<mx:transitions>
  <mx:Transition fromState="" toState="Stato3">
    <mx:Sequence targets="{[pnl1,pnl2,fin1,pnl4,button2]}">
      <mx:Parallel>
        <mx:Resize target="{pnl1}" />
        <mx:Fade alphaTo="0" target="{pnl2}" />
        <mx:Blur blurXFrom="50" blurXTo="0" target="{pnl1}" />
      </mx:Parallel>
      <mx:RemoveChildAction />
      <mx:AddChildAction />
      <mx:Fade alphaFrom="0" alphaTo="1" target="{fin1}" />
    </mx:Sequence>
  </mx:Transition>
</mx:transitions>

Conclusioni

Per certi aspetti gli stati di un'applicazione Flex possono essere paragonati ai diversi fotogrammi di un filmato Flash, dove ad ogni fotogramma è possibile disporre gli elementi in maniera diversa e aggiungere o rimuovere oggetti, tuttavia in Flash sarebbe necessario impostare (sulla timeline o tramite Actionscript) gli eventuali spostamenti ed effetti di ogni oggetto, con tempo e difficoltà maggiori e soprattutto senza la versatilità offerta da Flex, dove basta di fatto cambiare il tag MXML di un effetto con un altro per ottenere il risultato voluto.

Per quanto sia importante non esagerare con le transizioni, dato che gli stati sono più che sufficienti per variare l'interfaccia di una RIA, la versatilità e la semplicità con cui è possibile rendere animato il passaggio tra diverse visualizzazioni consente di ottenere prodotti visivamente accattivanti con uno sforzo pressoché minimo.


Ti consigliamo anche