¿Quieres registrarte?

Asignar eventos a botones de una película Flash desde un XML

Por: eldervaz
31 de Enero del 2009

Este tip se me ocurrió mientras desarrollaba una aplicación que contendría una gran cantidad de botones con distintos diseños, cada uno diferente, así que era imposible hacer un patrón y reutilizarlos. Además, cada uno de estos dispararía un enlace distinto que el cliente aun no sabía cual, así que el "editaría" después el FLA con la información final.

Cansado de convertir cada vector en botón y luego colocarle un nombre de instancia, pensaba en como haría el cliente para editar las url. Se me ocurrió crear un XML con los nombres de instancia de los botones y las URL, y así poder evitar que el cliente meta la mano al FLA.

La idea es simple y haremos un ejemplo inicial con 5 botones, para eso ya tengo un XML con los nombres de instancia y las URL de cada botón, algo así:

Código :

<data>
   <d btn='botonZguillez' url='zguillez.html'/>
   <d btn='botonZah' url='zah.html'/>
   <d btn='botonElecash' url='elecash.html'/>
   <d btn='botonXklibur' url='xklibur.html'/>
   <d btn='botonOtaku' url='otaku.html'/>
</data>


Por otro lado, tenemos nuestro FLA con los 5 botones y sus respectivos nombre de instancia(notemos que los nombres de instancia no llevan un patrón o son consecutivos).

Lo primero que haremos es cargar el XML mediante una clase

Código :

package cristalab.utils{
   
   import flash.events.*;
   import flash.net.*;
   
   public class LoaderXML extends EventDispatcher{
      
      public static var ACTION:String = "action";
      public var _data:XML;
      
      public function LoaderXML (){}

      //metodo para cargar el XML, recibe como paremetro la url del archivo
      public function loadXML(url:String):void{
         var urlLoader:URLLoader = new URLLoader(new URLRequest(url));
         urlLoader.addEventListener(Event.COMPLETE, complete);
      }
      
      private function complete(e:Event):void{
         _data = new XML(e.target.data);
         dispatchEvent(new Event(LoaderXML.ACTION));
         
      }
   }   
}


Ahora desde nuestra clase principal llamamos a la clase LoaderXML

Código :

package {
   
   import flash.events.*;
   import flash.display.*;
   import flash.ui.*;
   import cristalab.utils.*;

   public class Main extends MovieClip{
      
      private var t:LoaderXML;
      
      public function Main(){
         t = new LoaderXML();          
         t.loadXML("data/data.xml");
         //cuando cague el XML llamamos al metodo compare
         t.addEventListener(LoaderXML.ACTION, compare);
      }
      
      private function compare(e:Event):void{
         trace("aqui pondremos el código para hacer la magia");      
      }
   }   
}


Ahora si podemos empezar a hacer código en el método compare, para eso crearemos un for que nos permita recorrer el XML, sacando el nombre de instancia y verificando su existencia en el mcContenedor (gracias Otaku)

Código :

var tmpBTN:SimpleButton;
var name:String;
var miXML:XML = e.target._data;

for(var i:int=0; i< miXML.d.length() ; i++){
   name = miXML.d.@btn[i];
   if( mcContenedor.getChildByName( name ) != null )
   {
      //AQUI EXISTE EL BOTON
   } 
}


Ya casi tenemos todo listo, ahora solo nos queda agregar el evento al boton. También guardo el valor de i en tabIndex para saber la ubicación que tiene en el XML. El método queda así:

Código :

      private function compare(e:Event):void{
         var tmpBTN:SimpleButton;
         var name:String;
         var miXML:XML = e.target._data;
         
         for(var i:int=0; i< miXML.d.length() ; i++){
            name = miXML.d.@btn[i];
            if( mcContenedor.getChildByName( name ) != null )
            {
               tmpBTN = mcContenedor.getChildByName( name ) as SimpleButton; 
               tmpBTN.tabIndex = i; 
               tmpBTN.addEventListener(MouseEvent.CLICK, sayName); 
            } 
         }
      }


Ahora creamos nuestro método sayName y listo, tenemos nuestro FLA funcionando, aquí el código completo

Código :

package {

   import flash.events.*;
   import flash.display.*;
   import flash.ui.*;
   import cristalab.utils.*;

   public class Main extends MovieClip {

      private var t:LoaderXML;
      public function Main() {
         t = new LoaderXML();
         t.loadXML("data/data.xml");
         t.addEventListener(LoaderXML.ACTION, compare);
      }

      private function compare(e:Event):void{
         var tmpBTN:SimpleButton;
         var name:String;
         var miXML:XML = e.target._data;
         
         for(var i:int=0; i< miXML.d.length() ; i++){
            name = miXML.d.@btn[i];
            if( mcContenedor.getChildByName( name ) != null )
            {
               tmpBTN = mcContenedor.getChildByName( name ) as SimpleButton; 
               tmpBTN.tabIndex = i; 
               tmpBTN.addEventListener(MouseEvent.CLICK, sayName); 
            } 
         }
      }

      private function sayName(e:MouseEvent):void {
         trace(t._data.d.@url[e.target.tabIndex]);
      }
   }
}


Esto es simple, ahora imagina que si tienes que cambiar la url de algun btn, sólo lo harías en el XML ^^

Es más, ahora agrega 10, 20, 50 botones en el FLA, le pones nombre de instancia y todas las url en el XML :P solo editas ahi las url y listo, funciona ^^.

Pruébalo, esto salió como jugando y pensando en que uno aveces es flojo :P ya que con 36 líneas de código, puedes tener N cantidad de botones.

Aquí el ejemplo del tip





Ahora si no quieres usar tabIndex, podemos utilizar el código de Zguillez donde quedaría así:

Clase Main.as

Código :

package 
{
   import flash.display.MovieClip;
   import flash.display.SimpleButton;
   import flash.events.Event;
   import flash.events.MouseEvent;
   import cristalab.utils.LoaderXML;
   import cristalab.display.SimpleButtonURL;

   public class Main extends MovieClip
   {
      private var t:LoaderXML;

      public function Main()
      {
         t = new LoaderXML();
         t.loadXML("datos.xml");
         t.addEventListener(LoaderXML.ACTION, compare);
      }
      private function compare(e:Event):void
      {
         var total:uint = e.target._data.d.length();
         var i:uint;
         var name:String;
         var url:String;
         for (i=0; i<total; i++)
         {
            name = e.target._data.d.@btn[i];
            url = e.target._data.d.@url[i];
            if (this.getChildByName(name) != null)
            {
               var boton:SimpleButtonURL;
               boton = new SimpleButtonURL(this.getChildByName(name) as SimpleButton);
               boton.url = url;
            }
         }
      }
   }
}

Clase SimpleButtonURL.as

Código :

package cristalab.display
{
   import flash.display.SimpleButton;
   import flash.events.Event;
   import flash.events.MouseEvent;
   import flash.net.URLRequest;
   import flash.net.navigateToURL;

   public class SimpleButtonURL
   {
      private var _url:URLRequest;

      public function SimpleButtonURL(boton:SimpleButton):void
      {
         boton.addEventListener(MouseEvent.CLICK, _navigateToURL);
      }
      public function set url(u:String):void
      {
         _url = new URLRequest(u);
      }
      private function _navigateToURL(e:Event):void
      {
         if (_url!=null)
         {
            navigateToURL(_url);
         }
      }
   }
}


:) listo, espero les sea útil.

Enviar a twitter Enviar a facebook


También te interesa


Etiquetas xml actionscript_3 optimizacion

Comentarios | Enviar un comentario
Es muy útil hacer eso, hace las aplicaciones muy fáciles de actualizar y reutilizar ;)
Buen tip! quedó bien al final con todos los códigos (y)
Por: Zguillez
Baje el archivo, y no solo eso... ¡Lo probe! Debo decir, que realmente llega a facilitar mucho un posible actualizado.
Por: M@U
Para clientes indecisos, actualizaciones y mantenimiento esta de lujo Elder ;-)
Por: eparada
A eso le llamo, usar flash de una buena manera, I love XML U_U
Por: gcm
Muy interesante la solución, excelente tip!
Por: Woller
Esto es muy util para sitios con una gran cantidad de sub secciones y que tiendan a cambiar o desaparecer, o que subitamente la direccion interna del desarrollo cambie.
Por: absulit
Gran tip Elder...

Gracias por publicarlo!!!
Por: Camuss
una pregunta, para hacer que el boton tenga incluido un texto dinamico asigando del xml?
Por: lucasmoyano-blog
@lucasmoyano-blog: Agrega un parametro más en el XML y has lo mismo que con la url, solo que asignalo al campo de texto dinamico del boton
Por: eldervaz
genial el tip! una pregunta: para que tenga sonido el botón, como hago?
Por: Mila2
Saludos; quiero saber en donde está el link para bajar los archivos... Muchas Gracias.
Por: sarjuliancho
Deja un comentario
IMPORTANTE

Recuerda ser respetuoso, no insultes a otras personas, ni uses palabrotas, hay una persona al otro lado de la pantalla.

Habla bien, NO ESCRIBAS EN MAYUSCULA TODO, no escribas como en un SMS, evita cosas como "ke", "x q" y demás abreviaciones.

Aquí funcionan las etiquetas de los foros, puedes usar [b] para negrita, [img] para las imágenes, [url] para los enlaces, etc.

Si tienes preguntas técnicas, envíalas mejor al foro.