FLEX 3 - Chrome e RawChildren: aggiungere elementi visuali alle parti ‘protette’ di un componente
Tutti i componenti Flex sono essenzialmente formati da due sezioni: la classica area di layout, in cui e’ possibile inserire agevolmente elementi visuali tramite tag MXML o attraverso il classico metodo addChild(), e un’area definita Chrome rappresentata da tutti gli altri spazi, come barra del titolo, scrollbars, margini, footer e cosi via’ in cui solitamente e’ impossibile scrivervi.
Estenderemo quindi la classe Panel ridefinendo i suoi metodi createChildren() e updateDisplayList() (esponendo quindi il concetto di override di un metodo) e utilizzeremo la proprieta’ rawChildren per scrivere nella titleBar.
Per inserire nuovi elementi all’interno di queste aree “protette” sara’ quindi necessario creare una nuova classe che estende il componente Panel e utilizzare la proprieta’ rawChildren per scrivere all’interno della Chrome Area.
In questo esercizio vedremo quindi come inserire un componente Button all’interno della TitleBar del Panel e assoceremo a tale pulsante la funzionalita’ di resize 100% affinche’ ad ogni suo click il pannello venga esteso al 100% in altezza e larghezza (vedi immagine seguente)
ESTENDERE IL COMPONENTE PANEL
Innanzitutto creiamo un nuovo progetto Flex e inseriamo una nuova classe chiamata ExtendedPanel.as all’interno di una cartella denominata /view.
1. Questa classe dovra’ quindi estendere il componente Panel.
2. Inizializziamo alcune variabili per il posizionamento del pulsante RESIZE all’interno della barra del titolo e impostiamo le dimensioni di default del componente (utilizzate all’interno del costruttore)
3. Definiamo infine il pulsante resize che sara’ istanziato successivamente
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | package view { import mx.containers.Panel; import mx.controls.Button; import flash.events.MouseEvent; public class ExtendedPanel extends Panel { // Inizializzazioni private var marginRight:uint = 10; private var marginTop:uint = 5; public var panelWidth:uint = 200; public var panelHeight:uint = 100; // Pulsante RESIZE presente nella TitleBar private var resize:Button; // Costruttore public function ExtendedPanel() { // Dimensioni di default this.width = panelWidth; this.height = panelHeight; } } } |
NOTA: per semplicita’ definiamo i valori delle proprieta’ del componente Panel e del pulsante RESIZE all’interno della classe stessa ma sarebbe buona norma creare dei metodi pubblici setters affinche’ queste proprieta’ siano definite dall’esterno, ad esempio direttamente dal codice MXML che istanzia il componente.
rawChildren, createChildren, updateDisplayList e override di metodi
Finora non abbiamo fatto nulla di particolare ma di seguito dovremo invece ridefinire alcuni metodi del componente Panel. In gergo questa operazione viene chiamata override di un metodo.
CREATECHILDREN()
Il primo metodo che dobbiamo riscrivere e’ il metodo createChildren, tramite il quale sara’ possibile inizializzare il nostro pulsante di resize e i relativi listener.
Il codice e’ abbastanza semplice da intuire ed evidenziamo solo alcune particolarita’:
1) Per ridefinire un metodo gia’ esistente dobbiamo utilizzare la keyword override ed e’ necessario che la tipologia del metodo (in questo caso protected) e il numero di parametri (in questo caso nessuno) combacino esattamente con quello originale
2) E’ necessario inoltre chiamare il metodo createChildren della classe originale tramite l’istruzione super.createChildren()
3) Sfruttiamo la proprieta’ rawChildren, per inserire elementi all’interno della chrome area
4) Da notare che a questo punto il pulsante non e’ stato ancora posizionato
1 2 3 4 5 6 7 8 9 10 11 12 | // Inizializzazione pulsante RESIZE protected override function createChildren():void { super.createChildren() resize = new Button(); resize.label = "Res" resize.width = 50; resize.height= 20; resize.addEventListener(MouseEvent.CLICK, onClick) <strong>rawChildren.addChild(resize)</strong> } |
UPDATEDISPLAYLIST()
Il secondo metodo che dobbiamo ridefinire e’ updateDisplayList() che si occupa invece di posizionare il pulsante alle coordinate desiderate.
Questo metodo saro’ invocato ogni qualvolta il componente verra’ ridimensionato, ad esempio quando le dimensioni del componente sono reimpostate tramite codice actionscript oppure quando il browser viene ridimensionato e restituisce due parametri, unscaledWidth e unscaledHeight, che rappresentano le dimensioni aggiornate del componente.
Come per il metodo precedente invochiamo la relativa superclass e successivamente calcoliamo le posizioni del componente: mentre la coordinata Y del pulsante e’ definita semplicemente tramite la variabile marginTop definita in precedenza, la coordinata X variera’ a seconda delle dimensioni del componente, dato che il nostro pulsante dovra’ essere posizionato sempre al margine destro del pannello.
Sfrutteremo quindi il parametro unscaledWidth per conoscere la dimensione del componente, al quale sottrarremo la dimensione del pulsante RESIZE e il margine destro definito all’inizio della classe.
1 2 3 4 5 6 7 8 9 10 11 12 | // Posizionamento del pulsante protected override function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void { super.updateDisplayList(unscaledWidth, unscaledHeight) // Posizione X del pulsante RESIZE al margine destro var x:Number = unscaledWidth - resize.width - marginRight; var y:Number = marginTop; resize.move(x, y) } |
Definiamo infine il metodo onClick che si occupera’ semplicemente di effettuare il resize del componente dalle dimensioni originali a 100% e viceversa.
1 2 3 4 5 6 7 8 9 10 11 12 | private function onClick(e:MouseEvent):void { // Ridimensionamento del componento Panel if (this.percentWidth == 100) { this.width = panelWidth; this.height= panelHeight; } else { this.percentWidth = 100; this.percentHeight = 100; } } |
NOTA: al posto di definire le funzionalita’ del CLICK all’interno del componente potrebbe essere utile effettuare un dispatch dell’evento CLICK affinche’ le funzionalita’ siano invece definite dall’esterno (vedi tutorial Estendere il componente Combobox in AS3 per caricare dati XML). In questo modo sara’ possibile associare diversi comportamenti, sfruttando questo componente in diverse circostanze
IL CODICE COMPLETO
Per utilizzare il componente sara’ sufficiente creare un nuovo file MXML e inserire il seguente codice
1 2 3 4 5 6 7 8 9 | <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" xmlns:view="view.*"> <view:ExtendedPanel title="Test Chrome"> <mx:Text text="Layout Area" /> </view:ExtendedPanel> </mx:Application> |
Di seguito il codice completo della classe ExtendedPanel.as:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 | package view { import mx.containers.Panel; import mx.controls.Button; import flash.events.MouseEvent; public class ExtendedPanel extends Panel { // Distanza pulsante dal margine destro del componente private var marginRight:uint = 10; // Distanza pulsante RESIZE dal margine superiore private var marginTop:uint = 5; // Dimensioni di default del pannello public var panelWidth:uint = 200; public var panelHeight:uint = 100; // Pulsante RESIZE presente nella TitleBar private var resize:Button; // Costruttore public function ExtendedPanel() { // Dimensioni di default this.width = panelWidth; this.height = panelHeight; } // Inizializzazione pulsante RESIZE protected override function createChildren():void { super.createChildren() resize = new Button(); resize.label = "Res" resize.width = 50; resize.height= 20; resize.addEventListener(MouseEvent.CLICK, onClick) rawChildren.addChild(resize) } // Posizionamento del pulsante protected override function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void { super.updateDisplayList(unscaledWidth, unscaledHeight) // Posizione X del pulsante RESIZE al margine destro var x:Number = unscaledWidth - resize.width - marginRight; var y:Number = marginTop; resize.move(x, y) } private function onClick(e:MouseEvent):void { // Ridimensionamento del componento Panel if (this.percentWidth == 100) { this.width = panelWidth; this.height= panelHeight; } else { this.percentWidth = 100; this.percentHeight = 100; } } } } |














Leave your response!