0
votes

I'm building an ActionScript 3 project, and have found that writing some components in MXML would simplify things.

It seems like I'd need to extend the Flex Application class in order to do that. If that is right, how should I do that?

Currently my Main object extends Sprite. Other Sprites are then added to it with addChild(), and I'd like Flex components in one of those. Surely there is a way without rewriting my application completely in MXML?

1

1 Answers

2
votes

Edit As posted in the comments my explanation here is mostly regarding transitioning to a Spark application, the same kinds of ideas apply going to MX Application except with MX you could stick with addChild, generally speaking there you would need to implement IUIComponent to use containers see docs:

Note: While the child argument to the method is specified as of type DisplayObject, the argument must implement the IUIComponent interface to be added as a child of a container. All Flex components implement this interface.

http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/core/Container.html#addChild() End Edit

You can switch your base class to Application instead of Sprite, but when adding elements to a Flex 4 application it expects that they implement IVisualElement. Generally speaking you would switch your addChild calls to addElement, and you would have to change your other classes that currently extend Sprite/MovieClip/DisplayObject to extend something like Group so that they implement the necessary interfaces for Flex Application to work with them (generally it expects more things than lower level Flash objects provide since it has the LayoutManager, PopUpManager, Component Life cycle, etc.). The issue here is you'll be adding some weight to your components, if this is meant for the web or desktop I wouldn't be too concerned but this will affect performance on mobile devices, noticeably.

Unfortunately it's not a turn-key type solution, it requires some manual modification of the code since you have to make the call on what to change each object to based on it's functionality, sometimes Group is the right way to go other times you might get more benefit out of other containers or controls. In some cases you may want to stick with your current lower level extension (say extending Sprite) and just implement IVisualElement yourself.

http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/core/Container.html#addElement()

If you wanted to wholesale switch to using an MXML file for your application you could also create a basic MXML application file, and have it include a script block with your existing code (modified so constructor code is moved into creation complete). Alternatively you can have a base .as file that extends application then use that as the base class for your MXML, I'll throw together some examples.

Example 1 A very basic MXML Application file

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
               xmlns:s="library://ns.adobe.com/flex/spark" 
               xmlns:mx="library://ns.adobe.com/flex/mx"
               minWidth="955" minHeight="600">
    <fx:Script>
        <![CDATA[

        ]]>
    </fx:Script>
</s:Application>

Example 2 An AS3 Class extending application and an MXML class extending that

[Main.mxml]

<?xml version="1.0" encoding="utf-8"?>
<MyBaseApp
           xmlns="*"
           xmlns:fx="http://ns.adobe.com/mxml/2009" 
           xmlns:s="library://ns.adobe.com/flex/spark" 
           xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600">
    <s:Button id="btnControl"/>
</MyBaseApp>

[MyBaseApp.as]

package
{
    import mx.events.FlexEvent;

    import spark.components.Application;
    import spark.components.Button;

    public class MyBaseApp extends Application
    {
        public var btnControl:Button;
        public function MyBaseApp()
        {
            super();
            addEventListener(FlexEvent.CREATION_COMPLETE, creationCompleteHandler);
        }
        private function creationCompleteHandler(event:FlexEvent):void
        {
            btnControl.label = "something I set in AS3";
        }
    }
}