====== Flex y MXML con Flex Builder y otras plataformas ======
===== Base =====
==== Creación de un proyecto ====
Al crearse un proyecto de Flex mediante Flex Builder, se crea un archivo mxml con el mismo nombre que el proyecto. Este contiene el siguiente código:
Esta es la aplicación principal (el tag //// dentro del archivo .mxml con el mismo nombre que el proyecto), aún así podríamos cambiarlo (en el Flex Builder, botón derecho -> Set as default application).
* Podemos asignar una URL al proyecto, esto nos será útil cuando este lea una fuente de datos y necesite recogerla por http, para ello en el proyecto -> propiedades -> Flex Build Path -> Output Folder URL
==== Objeto ====
* Como ya hemos visto este objeto representa la aplicación principal, podemos configurarla para que los bordes se ajusten al explorador indicandolo por tantos por ciento:
* Su evento //creationComplete// se ejecuta cuando ha cargado todos los controles, por lo que podemos asignarle un método que se llamará al iniciarse la apliación.
===== Controles =====
* Dentro de una aplicación pueden añadirse distintos controles con la misma sintaxis que la aplicación:
contenido mx:control>
* La propiedad id permitirá al elemento ser accedido desde código, el valor de esta debe de ser único.
* Puedes enlazar (por ejemplo) el texto de una label a el valor de un control, para ello debes poner ese valor entre corchetes. Podría ser algo así:
* Enlaza el texto de una label al valor de un combo (con id = cmb).
==== Controles conocidos ====
* ****
* Las propiedades 'width', 'height', 'x' e 'y', existen para este control.
* ****
* ****
* La propiedad label permite asignarle un texto
* El evento para los clicks corresponde a la propiedad click.
* La propiedad toggle (que recibe true\false) indica si es un botón con estados (si se pulsa, se queda pulsado y viceversa).
* ****
* ****
* El evento para cuando se cambia de elemento en el condo es la propiedad change.
* Podemos asignar un texto a mostrar antes de seleccionar un elemento del combo mediante la propiedad prompt.
* ****
* ****
* Contenedor de controles que permite colocarlos todos ordenadamente.
* ****
* Este control está formado de columnas, para crearlas dentro de su tag debe de existir otra llamada , esta englobará objetos ////.
* ****
* Podemos indicar que, en una lista, puedan definirse más de un elemento mediante su propiedad allowMultipleSelection.
* La propiedad rowCount es la que restringe el número de elementos que se mostrarán.
Podemos definir los tamaños de los controles en tantos por ciento respecto a su contenedor.
==== Añadir elementos a un combo ====
Dentro del cuerpo del combo crearemos objetos con las propiedades //label// y //data//. En label estará el texto que se mostrará para el elemento y dentro de data su valor asociado:
Ahora, mediante ActionScript, podemos acceder al valor seleccionado del combo con un //cmb.value//. \\
De la misma forma también podemos asignar un array mediante un //dataProvider//:
SatisfiedNeutralDissatisfied
Podemos asignar un dataProvider de otra forma, mediante la propiedad //dataProvider// del control. Por ejemplo:
El //Currency// del ejemplo será un array definido en el código ActionScript: ''public var Currency:Array = ["US Dollars", "Euro"];''
==== Posicionamiento absoluto ====
Al tener la aplicación como //layout="absolute"// podemos colocar los elementos donde queramos, siempre se quedarán ahí, aunque el explorador donde estén colocados sea redimensionado ellos seguirán con un tamaño estático. Aún así, nosotros podemos cambiar esa propiedad asignando unos márgenes, de esta forma, ya se haga más grande o más pequeño el tamaño del explorador, los controles tendrán un tamaño relativo. \\
Para asignar dicho márgen existen las propiedades //left, right, top// y //bottom//:
Estas propiedades, en el Flex Builder, se editan desde el apartado //constraints//.
==== Posicionamiento ====
Hay tres formas de posicionar los controles:
* Colocando la propiedad layout del contenedor como **absolute** podremos indicar las posiciones x e y de los controles.
* Usando otros valores a layout para que los controles se ordenen automáticamente. Por ejemplo tenemos las siguientes posivilidades:
* **layout**: absolute, horizontal (coloca los controles en fila), vertical (los coloca en columna).
* **horizontalAlign**: left, center o right
* **verticalAlign**: top, middle, bottom
* **padding** (es el margen para los controles)
Por ejemplo, colocando en el contenedor el layout como //horizontal// y el //verticalAlgingn// como //middle// hará que los controles se inserten en el centro del contenedor en una fila.
* Anclando los controles, asignando los valores a sus propiedades //top, bottom, left, right//. Que asignando valores a todas estas propiedades el control se adapta a su contenedor.
* También podemos anclarlos al centro mediante //horizontalCenter// y //verticalCenter//, que si pones las dos a 0 el control se coloca en el centro.
==== Crear controles personalizados ====
Crear un componente desde el Flex Builder es sencillo, sólo has de añadir nuevo componente, dar su nombre y buscar en qué elemento se basa. Una vez lo tengamos, veremos que el código es como el de una aplicación pero siendo la tag principal la correspondiente al elemento escogido. \\
Por ejemplo si escogemos un ////:
==== Eventos ====
=== Utilizando MXML ===
* Asignar un evento mediante el Flex Builder (MXML) a una función es fácil. Por ejemplo para un botón sólo has de ir al panel de propiedades y en el campo //onClick// asignar el nombre de una función, por ejemplo: //Convert()//. Esto añade a la tag del botón la propiedad: //click="Convert()"//.
* Podemos asignar más funciones o introducir código, separado por ; dentro de estas llamadas de eventos:
click="blurEffect.play(); myLabel.visible=true;"
* Cuando se hace el click (o cualquier otro evento en mxml) se crea un objeto event que podemos pasarlo al método que llamamos:
* Ahora la función recibe un objeto Event:
function funcion(e:Event):void { }
* El objeto Event tiene una propiedad llamada target que corresponde al elemento que lo ha llamado.
=== Utilizando ActionScript ===
Para asignar un evento por ActionScript, como en mxml, debe de existir una función que será la que ejecute el código asociado al evento, pero esta debe de recibir un parámetro del tipo Event, por ejemplo:
public function Convert(e:Event):void
Ahora debemos crear un EventListener asociado a Convert para el evento Click del botón, esto es un "escuchador de eventos" que cuando se lance el evento Click en el botón se llamará a Convert:
boton.addEventListener(MouseEvent.CLICK, Convert);
Lo más adecuado es meterlo dentro de una función que llamaremos al acabar de crear el interface, algo así:
public function createListener():void {
boton.addEventListener(MouseEvent.CLICK, Convert);
}
Para que se llame tras haberse acabado de crear el interface, es decir, tras haberse acabado de ejecutar el tag Application, debemos añadir a este () la propiedad siguiente:
creationComplete="createListener();"
===== Contenedores =====
Existen varias clases que pueden llegar a contener controles y poder ordenarlos o tratarlos de forma específica:
* **Panel**: Muestra un título, un borde y sus hijos.
* **HDividedBox\VDividedBox**: Contenedor que inserta un divisor en medio.
* **Title**: Para ordenar los elementos en columnas y filas.
* **Form**: Ordena los controles como un formulario standard.
* **ApplicationControlBar\ControlBar**: Acopla los elementos en una barra de control, la primera para toda la aplicación, la segunda para otro contenedor (p.ej. un Panel).
* **Canvas**: Otro contenedor, pero este invisible.
==== Contenedores de navegación ====
Para insertar controles en un contenedor de navegación debemos insertar antes en él un contenedor corriente (p.ej. un canvas, para el título de los apartados usaremos su propiedad label). Existen los siguientes contenedores de navegación:
* **Accordion**: Introduciremos varios contenedores y se mostrarán en formato de acordeón.
* **TabNavigator**
* **ViewStack**: Muestra únicamente uno de sus contenedores, para cambiar de contenedor debemos de usar uno de los siguientes controles: //LinkBar, TabBar, ButtonBar, TolggleButtonBar//, a los cuales debemos asignar a su propiedad //dataProvider// el id de la //ViewStack// entre corchetes y se llenarán solos, con los títulos de los contenedores.
===== Elementos visuales =====
==== Behaviors ====
Podemos definir comportamientos para los controles, otra forma de decir "comportamientos" sería "efectos". Los efectos en Flex también tienen sus propias tags, estas no han de definirse dentro de contenedoras (paneles formularios...), sino dentro de la aplicación:
Para asignarlos mediante el Flex Builder iremos a la vista por categorías de un control y se lo asignaremos en el apartado de efectos mediante su id entre corchetes. En código debe de quedar así:
* ****
* Es una transición de alpha. Se indica un color (color), un alpha inicial (alphaFrom) y otro final (alphaTo), también el tiempo (duration).
* ****
* Es un efecto que muestra borrosos los elementos del control y poco a poco los aclara. Sus propiedades: duration, blurYFrom, blurYTo, blurXFrom y blurXTo.
* ****
* Efecto de movimiento. Propiedades: duration, xBy (incremento de x), yBy.
* ****
* Hace más grande\pequeño un control. Propiedades: duration, zoomHeightTo, zoomWidthTo.
Podemos asignar a un control el efecto mediante la propiedad target, el id del control deberá ir entre corchetes: //target="{myLabel}"//. Sabiendo que mediante ActionScript podemos iniciar un efecto mediante //idEfecto.play()//, podríamos, por ejemplo, al apretar un botón se llame al play de un efecto que tiene un target asignado. (También existe el método //idEfecto.pause()// y el //idEfecto.resume()//). \\
Podemos crear efectos combinados, es decir, grupos de efectos que se ejecutan como si fuesen uno. Para ello usamos la tag , le damos un id y un target, y en su cuerpo introducimos los efectos que la componen:
Ahora sólo tendremos que hacer un //BlurMoveShow.play()// para que los efectos Blur y Move se ejecuten sobre myLabel.
* Otro ejemplo, un botón que se hace pequeño al pulsar y vuelve a su estado al dejar de pulsar:
==== Estados ====
* En nuestra aplicación de flex, podemos mostrar u ocultar ciertos elementos, por ejemplo, opciones de una búsqueda. La creación de los estados, en el Flex Builder se hace mediante la ventana //States//.
* Un estado se basa en otro, es decir, por defecto es idéntico al otro pero añadiendo nuevos controles (o quitando los que ya tiene). En código están contenidos en la tag ////.
* Para cambiar de estado usaremos la propiedad de ActionScript currentState, esta propiedad corresponde a un string con el nombre del estado actual, al cambiarla el estado cambia. Para volver al estado inicial deberemos igual currentState a vacío:
currentState='Advanced'
currentState=''
Esto lo podríamos hacer en la propiedad click de un botón, en el estado stándard: //click="currentState='Advanced'"//. Y en el estado Advanced cambiaríamos el código anterior por currentState=''
==== Transiciones entre estados ====
* Las transiciones las creamos a parte, en el bloque //// que lo situaremos dentro del ////. Dicho bloque contiene otros "sub-bloques" de ////.
* Una Transition tiene como propiedades básicas id (identificador), fromState (id del estado con que inicia) y toState (id del estado con el que acaba).
* Cuando en la propiedad fromState y/o en la toState en vez de colocar un id colocamos un * esta transición nos servirá para pasar a todos los estados. \\
Por ejemplo, para crear una transición llamada 'myTransition' que vaya del estado inicial al 'Advanced' haremos lo siguiente:
Ahora debemos definir qué efecto se usará para la transición, al efecto deberemos darle un target (objeto que realizará dicha transición), para ello colocaremos su id entre corchetes:
* Podemos agrupar transiciones, esto es, al pasar de un estado a otro que se realicen varias transiciones. La forma en la que estas se realizan puede ser o , en la que hasta que no acaba la primera no empieza la segunda. A estas tags serán a las que les demos el target, por lo tanto, a las internas no les será necesaria esta propiedad:
* ****
* El elemento al cual está aplicado aparece de arriba abajo.
* ****
* El elemento al cual está aplicado empieza con el valor de alpha indicado en la propiedad alphaFrom y acaba con el valor de alphaTo.
* ****
* Los elementos empiezan mostrandose borrosos.
* ****
* Hace que los elementos a los que se les aplica cambién de tamño.
* En la tags //// o //// podemos indicar más de un target, para ello existe la propiedad targets, que recibe un array:
* En una transición podemos aplicar ciertos efectos usando la propiedad easingFunction, como por ejemplo:
==== Estilos CSS para los controles ====
* Puedes usar hojas de estilo en cascada (CSS) en la programación flex, ello es muy sencillo, sólo has de usar la tag ////, si la css es externa:
* ...o interna:
.myclass { color: Red } /* class selector */
Button { fontSize: 10pt; color: Yellow } /* type selector */
* Ahora para asignar una clase de estilos a un control únicamente debemos indicar el nombre de esta en la propiedad //styleName//.
* Podemos definir un estilo mediante AS con el método setStyle de un control. P. ej. para la label anterior: ''lbl.setStyle("color", "Red");''
===== Enlace a datos =====
Para que un objeto que se enlace a datos (por ejemplo HTTPService) pueda acceder a una fuente de datos (por ejemplo un xml de feeds) se han de cumplir una de las siguientes premisas:
- El archivo .swf debe de estar alojado en el mismo dominio que la fuente de datos.
- En la raíz del dominio donde está la fuente de datos debe de existir un archivo [[sp:flex_xtra#archivo_crossdomain.xml|crossdomain.xml]] que esquecifique el acceso.
- Debes de poder acceder mediante un proxy (creado en lenguajes como JSP, ColdFusion, ASP...).
==== Objeto HTTPService ====
Te permite acceder a un servicio web mediate http, las propiedades más destacadas (a parte del id) son //url// (dirección del lugar donde se accederá) o //useProxy// (que indica si se usa o no un proxy).
Deberemos hacer //idHttpService.send()// para que se carguen los datos. Podríamos por ejemplo hacerlo tras haberse cargado la aplicación:
==== Llamar a un WebService ====
* Para acceder a un webservice necesitamos usar el objeto ////, este objeto no es muy distinto a los demás, sus propiedades más destacadas son id, //useProxy// y //wsdl// (dirección de webservice).
* La tag //// describe la operación que se va a hacer del WebService, la propiedad name ha de contener el string con el nombre del "método" que llama. Y en la tag //// que situaremos dentro de //// colocaremos las tags correspondientes a los parámetros pasados.
* Para llamar a la acción deberemos hacer: ''id del WebService.Nombre de la acción.send()'' \\
Por ejemplo, vamos a hacer una llamada a la acción de un webservice llamada 'getMostPopularPosts', a la cual se le pasan los parámetros daysBack y limit:
30{combo.value}
Para llamar a este webservice deberemos hacer:
wsBlogAggr.getMostPopularPosts.send()
==== Enlazar un control a una fuente de datos ====
* Por ejemplo, para un //DataGrid// deberíamos definir la fuente de datos con la propiedad //dataProvider//. Y para sus columnas usaremos la dataField.
* Por ejemplo queremos acceder a un xml de un rss, tenemos un objeto //// con //id=feedRequest//, cuando se llame al método send el objeto recibirá los datos y la propiedad //lastResult// se llenará de los datos del xml.
* Este xml está formado con la siguiente jerarquía: tag principal 'rss' -> tag 'channel' -> grupo de tags 'item'. Cada item contiene la tag 'title', 'description', 'link', 'category' y 'pubDate'. \\
Si queremos que el DataGrid se enlace a los elementos item asignaremos su dataProvider así:
dataProvider="{feedRequest.lastResult.rss.channel.item}"
Ahora deberemos enlazar sus columnas, una al título y otra a la fecha de publicación:
Ya tenemos el grid enlazado a los datos, ahora si queremos que en un texto a parte se muestre la descripción del "item" clicado sólo debemos hacer:
Otro ejemplo sería el de enlazar el DataGrid al resultado de una llamada a un webservice, el dataProvider se declararía así:
dataProvider="{iDWebService.NameOperation.lastResult}"
dataProvider="{wsBlogAggr.getMostPopularPosts.lastResult}">
Las columnas seguirían teniendo el dataField que les tocase según lo devuelto por el WebService.
* Al enlazar una lista\combo a una fuente de datos, el elemento que muestre será un Objeto, por lo que el texto no estará configurado, pero si el elemento a mostrar tiene como nombre de campo 'label' entonces nos irá guay! \\
P.Ej. unos datos como estos:
0
En una lista como esta:
Se nos mostrará el elemento de la tag label, si la tag hubiese sido nombre no hubiese sido correcto.
* Podemos mostrar el id en un texto:
===== GUIs =====
==== Imágenes ====
* Para añadir una imágen has de usar la tag su propiedad source es la que indica la dirección de esta.
* Aún así podemos también incrustarla en el compilado usando @Embed, de esta forma la imágen no deberá ser añadida en la carpeta, ya está en el swf.
* Pero, tal como la hemos incrustado sólo puede ser accedida por esa tag, si la queremos usar en otra deberíamos volver a añadirla. Aún así podemos añadirla para todo el código enlazándola a una clase de AS.
[Embed(source="tortuganinja.jpg")]
[Bindable] public var tortuga:Class;
Ahora, para usarla en una imágen:
* Debemos usar el tipo 'Class' para incrustarla ya que sólo este tipo (a parte del String) puede ser incrustado.
* Podemos enlazar una imágen y escalarla sólo centralmente (scale-9), esto es, usar los bordes a modo de marco. Para ello debemos indicar los bordes mediante las porpiedades scaleGridTop, scaleGridBottom, scaleGridLeft y scaleGridRight:
[Embed(
source="assets/fancy_border.png",
scaleGridTop="55", scaleGridBottom="137",
scaleGridLeft="57", scaleGridRight="266"
)]
==== Incrustar... ====
* Estilos, usaremos el Embed:
Button
{
upSkin: Embed("assets/box_closed.png");
overSkin: Embed("assets/box.png");
downSkin: Embed("assets/box_new.png");
}
* Ficheros SWF, se tratan igual que las imágenes, es más, para mostrarlos usamos el tag .
[Embed(source="assets/hourglass.swf")]
[Bindable] public var Hourglass:Class;
* Elementos de una biblioteca de un swf, sólo debemos usar la propiedad symbol a parte de la source para indicar el nombre del elemento:
[Embed(source="assets/library.swf", symbol="BadApple")]
[Bindable] public var BadApple:Class;
* Un sonido, como cualquier otro elemento:
[Embed(source="assets/pie-yan-knee.mp3")]
[Bindable] public var Song:Class;
* Sólo debemos de saber cómo convertir esa clase Song en un objeto compatible de sonido (SoundAsset):
public var mySong:SoundAsset = new Song() as SoundAsset;
==== Fuentes de texto no comunes ====
Para utilizarlas debemos añadir el archivo .ttf de la fuente en nuestro directorio de trabajo y enlazarla dentro de la etiqueta style:
@font-face
{
font-family: sands;
src: url("sands.ttf");
}
Ahora ya podemos usarla en un texto:
==== Formularios ====
Para la creación de formularios existe un elemento que nos facilitará la vida, el . Equivale a un elemento de formulario, este contiene una Label (propiedad label del mx:FormItem) y un control que se incluye entre sus tags de inicio y cierre:
==== Tooltips ====
* Para agregar un tooltip a un control únicamente debemos poner el texto que contendrá en su propiedad 'tooltip'.
* Podemos definir estilos para los tooltips dentro de la tag poniendo algo así:
ToolTip
{
fontFamily: "Arial";
fontSize: 10;
color: #FFFFFF;
backgroundColor: #000000;
}
* Si colocamos un tooltip en un contenedor, sus controles heredarán ese tooltip.
==== El fabuloso mundo del cursor ====
De tal mundo no es necesario mucho conocimiento. Únicamente debemos saber que para poder trabajar con el cursor tenemos la necesidad de importar en nuestro proyecto la clase: //mx.managers.CursorManager//.
import mx.managers.CursorManager;
* Ahora, en esta clase tenemos dos métodos para mostrar\ocultar respectivamente el cursor en espera: //CursorManager.setBusyCursor()// y //CursorManager.removeBusyCursor()//.
* Podemos elegir una imágen o un arhivo swf como cursor. Una vez lo carguemos tenemos una variable del tipo Class, pues debemos pasarle el nombre de dicha variable al método setCursor del CursorManager:
CursorManager.setCursor(VariableImagen);
* Una vez hayamos cambiado el cursor, para volver al cursor standard pasaremos al //setCursor// la viariable //CursorManager.currentCursorID//.
===== Xtra =====
==== Scripts ====
Los scripts se introducen dentro de la tag . Se usa la tag que al crearla en el Flex Builder te aparece lo siguiente:
* El CDATA es un adaptador para el script, que va dentro del cuerpo de este, para que pueda ser leido correctamente en MXML.
* Puedes usar un script de un fichero de código .as mediante la propiedad de la tag llamada source: source="sourcecode.as".
==== Repeater ====
Corresponde al componente //// y lo que hace es emular, en sintaxis MXML un bucle for. \\
Por ejemplo, tenemos un array de objetos de una clase producto, esta tiene como una de sus propiedades 'name'. Ahora, lo que hacemos es enlazar el //dataProvider// del //// al array (productsAC) y dentro de este colocamos el control que queremos que se repita:
Aún más sencillo, tenemos un array (myArray) y queremos que se nos muestre dicho array en labels:
Como vemos, la propiedad //currentIndex// del Repeater corresponde al elemento en el que se está en la iteración.
==== Skinning ====
Podemos crear skins para nuestros controles, por ejemplo, embeber una imágen y usarla como botón mediante los estilos:
Button
{
upSkin: Embed("box_closed.png");
overSkin: Embed("box.png");
downSkin: Embed("box_new.png");
}
El botón que se ha introducido en el código (sin id ni nada) se mostrará como una imágen (box_closed) que cuando se ponga el ratón por encima mostrará otra (box) y cuando se haga click otra (box_new).
==== Scale-9 ====
Podemos usar el scale-9 para hacer marcos para los textos:
.scale9Background
{
background-image: Embed("assets/fancy_background.png",
scaleGridTop="55", scaleGridBottom="137",
scaleGridLeft="57", scaleGridRight="266");
background-size:"100%";
}
VBox
{
padding-bottom:50;
padding-top:50;
padding-left:60;
padding-right:60;
}
La VBox conteine un texto que tiene el fondo indicado con scale-9.
==== Item Renders ====
=== Cargar un Grid con un archivo xml ===
El archivo xml tiene la siguiente estructura: //0. arwork -> 1. piece -> 2.name, image, price, quantity// \\
El artwork es el elemento raíz, contiene varios pieces y cada uno con name, price y quantity, quantity es un número, igual que price, nombre es su nombre, e image es una ruta de una imágen:
The Wallartwork1.jpg2505...
=== Hacer que el anterior grid muestre la imágen y un incrementador de unidades ===
Para que esto haya podido ser posible la clase del debe heredar de las interfaces IDropInListItemRenderer.
=== Usar componente creado en el mismo mxml como item rendered ===
* Componente (imágen con título):
* Grid:
=== Crear componentes externos como item rendered ===
* Archivo para el componente ImageRenderer:
* Archivo para el componente NumericStepRenderer:
=== Crear el componente en la misma columna ===
===== Notas =====
* Los comentarios en mxml van entre .
* Los comentarios en AS van entre /* ... */
* Para indicar que se puede ver el código fuente de la página (al hacer botón derecho) añadiremos la propiedad //viewSourceURL// a la tag //Application//.
* Otro elemento que podemos usar en Flex es el texto simple, para ello usaremos la tag: ////
* Si queremos colocar un salto de línea en un texto usaremos la siguiente combinación de carácteres:
.
* Existe un control llamado ////, que inserta un espacio invisible para el usuario entre controles (para cuando los insertes automáticamente).
* Si queremos insertar en un string otro que está en una variable haremos: ''var nombre:String = "texto {variable} texto";''
* La función //Alert.show(string)// nos mostrará un mensaje de alerta.
==== Otras plataformas ====
=== Visual Studio ===
Para desarrollar con Flex a partir de Visual Studio 2008 necesitarás el plugin Ensemble.
* Aquí un link de cómo utilizarlo: http://www.developerfusion.com/article/9536/using-adobe-flex-in-visual-studio/
===== Enlaces =====
* Proyectos Flex utilizados para documentar
* [[script:as3|ActionScript3]]
* {{highlevel:flex:integrating_flex2_and_php.pdf|Integrando Flex2 y PHP}}
* {{highlevel:flex:using_flex2_and_amfphp.pdf|Usando Flex2 y AMFPHP}}