Este pregunta fue la primera en el foro que cree la semana pasada, y es una excelente pregunta tanto para empezar tanto para empezar el foro y para demostrar el uso de componentes en Flex.La pregunta original cuestiona sobre como insertar un ApplicationControlBar en el encabezado del Panel, pero mi respuesta aquí explicara algo más genérico, como insertar cualquier componente en tal cabecera.
Para los que no son tan familiares con el Panel en Flex, este tiene un encabezado, el titleBar, el cual tiene propiedades para poner el titulo del panel (title) y su status (status). Pero hay ocaciones que queremeos agregar mas opciones a tal encabezado. Pero como hacerlo? Cual es la mejor manera de agregar tales elementos?
Tenemos que resolver dos problemas en este caso, primero como insertar tales componentes en el encabezado y segundo, como hacer que el Panel responda a la interacción con esos componentes. En este ejemplo, para demostrar el primer caso agregare un componente al encabezado el cual contiene un solo botón, el cual dispara un evento, y para el segundo agregare lógica en el panel para escuchar por tales eventos y modificar el Panel, en este caso maximizar y minimizar dicho Panel. Como veran el manejo de eventos en Flex es muy necesario para desarrollar componentes. Si necesitan un repaso, pueden ver la ayuda de Flex o esta entrada que al respecto escribi el otro dia.
Primeramente enlistare los pasos que seguí:
-
-
Cree un componente – ActionBar.mxml - que contiene un botón y que dispara los eventos maximizarPanel y minimizarPanel. Como verán en el código, este componente es completamente independiente y puede ser usado con cualquier propósito. Es más, el nombre de los eventos podría ser más genérico, pero he decidido dejarles los nombres que tienen por motivos didácticos. Puede ver que tiene una variable (maximizado) para mostrar ‘-‘ o ‘+’ como un indicativo visual de su propósito, es decir, maximizar (+) o minimzar (-) el Panel.
-
Cree un componente que extiende el Panel - PanelBar.mxml. Este componente es que el sobre todo nos interesa, ya que aquí esta el codigo que nos muestra primero como adicionar (ActionBar.mxml al titleBar del Panel ( usando createChildren y layoutChrome) , y segundo como responder a eventos disparados en ActionBar.mxml dentro de PanelBar.mxml ( usando addEventListener)
-
Cree una aplicación solo para demostrar el ejemplo : PanelComponentApp.mxml
Pero detengámonos un poco más en las funciones createChildren y layoutChrome usadas en este caso. Si ya las han usado o están familiarizados con programación orientada a objetos los calificadores override protected no les serán extraños, pero si no es así, bueno piensen que lo que estan dicendole al Panel es algo como, “ hey Panel! Quiero que ejecutes esas funciones tal como ya sabes (lo cual indicamos llamando super.createChildren()), pero además quiero que ejecutes esto otro...”, es nuestro caso adicionar ActionBar.mxml al titleBar y posicionar ActionBar en layoutChrome. Como menciono en los comentarios, layoutChrome es llamado cada vez que se re-dibuja o actualiza el titleBar, lo cual lo hace el lugar perfecto para posicionar nuestro componente ActionBar. Podríamos haber usado UpdateDisplayList, sin embargo este es llamado cada vez que cualquier cosa cambia en el Panel, por ejemplo si adicionáramos contenido dinámicamente al Panel. Usando layoutChrome, el cual es solo usado para el titleBar y borders del Panel, nos ahorramos varias llamadas innecesarias. Pero no olvidemos que esto ultimo es solo cierto para el Panel. Si están usando addChild en cualquier otro componente, seguramente tendrían que usar UpdateDisplayList para posicionarlo. Al mismo tiempo si el autoLayout del Panel es puesto a false o true, el layoutChrome es llamado en ambos casos.
Asi pues es tiempo que les muestre el codigo o no? El propósito es meramente didáctico, y les queda de tarea tomar el concepto y crear sus propios componentes. Por ejemplo, en una versión completa, ActionBar seguramente puede usar customEvents para hacer el código mas genérico, y tal vez los botones puedes usar skins para mejorar su apariencia, y estos seguro que muchas mas.
Cuales ideas se les ocurren a ustedes?
--- ActionBar.mxml-----------------------------------------------------------------------
<?xml version="1.0" encoding="utf-8"?>
<mx:HBox xmlns:mx="http://www.adobe.com/2006/mxml" width="55">
<mx:Script>
<![CDATA[
[Bindable(event="maximizarPanel")][Bindable(event="minimizarPanel")]
[Bindable] public var maximizado : Boolean = true;
public function resizePanel ( event : MouseEvent) : void
{
if( maximizado )
{
dispatchEvent(new Event("minimizarPanel"));maximizado = false;
}
else
{
maximizado = true;dispatchEvent(new Event("maximizarPanel"));
}
}
]]>
</mx:Script>
<mx:Button label="{maximizado?'-':'+'}" width="50" click="resizePanel(event)"/>
</mx:HBox>
--- PanelBar.mxml-----------------------------------------------------------------------
<?xml version="1.0" encoding="utf-8"?>
<mx:Panel xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" width="400" height="300">
<mx:Script>
<![CDATA[
private var actionBar : ActionBar ;
// Usar createChildren para adicionar la barra con botones ( u otro componente)
override protected function createChildren ( ) : void
{
super.createChildren(); actionBar = new ActionBar();
// Los eventos que el ActionBar envia al panel
actionBar.addEventListener("maximizarPanel",cambiaPanel); actionBar.addEventListener("minimizarPanel",cambiaPanel);
// Finalmente adiciona el componente Action Bar al titleBar del Panel
titleBar.addChild(actionBar);
}
// Cuando el panel necesita actualizar borders o el titleBar lo hace a traves llamando layoutChrome
// Usamos ese evento para darle tamaño y posicionar nuestro componente ActionBar
override protected function layoutChrome ( unscaledWidth:Number, unscaledHeight:Number) : void
{
super.layoutChrome(unscaledWidth,unscaledHeight);
actionBar.height = actionBar.measuredHeight;
// Usar el posicionamiento de acuerdo al componente, en este caso solo centro verticalmente y
// lo pongo al lado del statusTextField del Panel
actionBar.move( statusTextField.x - actionBar.width, (titleBar.height - actionBar.height ) / 2);
}
// Un ejemplo simple de maximizar/minimizar el panel.
private function cambiaPanel ( event : Event ) : void
{
if ( event.type == "minimizarPanel" )
{
this.height = this.titleBar.height ;
}
else if ( event.type == "maximizarPanel" )
{
this.height = 300;
}
}
]]>
</mx:Script>
<mx:Text text=" Contenido del Panel"/></mx:Panel> --- PanelComponentApp.mxml-----------------------------------------------------------------------
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" xmlns:local="*">
<local:PanelBar width="300" height="300" title="Mi Panel" status="Normal"/>
</mx:Application>
Compilado usando Flex Builder 3