Archive for the ‘AS3’ tag
My MAX 2011 session: Discover The Unknown Flex 4.5
This year at MAX I did a geeky session about things that people don’t usually know about AS3, Flex and Flash Builder. Below you can find recording of my session and the slides.
Discover the unknown of Flex 4.5 – MAX session input request
During this year’s MAX I will be doing a presentation about things that are very useful but for some reason little known and rarely used in everyday Flex and AS3 development. The name of my session is “Discover the Unknown Flex 4.5”. This session is for you if you wants to learn new Flex/AS3 tips & tricks, check if you really know everything about Flex, and/or share your knowledge with others.
One of my goals is also to let anyone share their own tips & tricks so I’m expecting to initiate a free form discussion during the session. If you will not be attending this year’s MAX, I encourage to send me your input in advance. I will include most interesting proposals in my presentation, of course giving attribution to their authors
You can use this contact form or use comments below to send me your input.
So see you at MAX 2011…
as3viewnavigator 2.0.0 RC1 released!
I’m proud to announce a new release of the as3viewnavigator library. This new release is labeled with a 2.0.0 RC1 version number. Since the previous release the source code has been almost entirely rewritten to provide a host of new features, many bug-fixes and increased extensibility. The changes have likely also introduced some new bugs, so that is why this is an RC1 (Release Candidate 1) even though I think it is feature complete. Before it goes final I want to test it myself in battle and also have others provide input and bug reports. If you used previous versions I’m certain it will break your existing code (for your reference, the previous version is still available in github under the 1.0.0 tag.
So what is new:
- You can use
ViewNavigatorfor Flex (desktop) projects! At least until ViewNavigator from Flex Hero will not be available for desktop projects
ViewNavigatorhas become a container (based on the Sprite class for AS3 projects and theUIComponentfor Flex) now. Its default behavior in AS3 projects when added to the stage is that it takes 100% of the stage area and it auto-resizes itself. You also have an option to controlViewNavigatorwidth and height values explicitly. When using Flex you can lay it out anywhere in your MXML declaration like any other Flex component.- Default implementations of the
IViewinterface calledVieware provided for both AS3 (based onSprite) and Flex (based onSkinnableContainer) projects. - When performing actions on
ViewNavigator(like pop, push, etc.) aViewNavigatorEvent.VIEW_CHANGINGevent is dispatched. This event is cancelable so application logic can prevent the view change. Also the event has additional properties likeoldViewandnewViewwhich enable access to the instances of exchanged views. - It is now possible to add custom view transitions. This can be done by implementing the
IViewTransitioninterface and setting its implementation instance to theViewNavigatorobject’sdefaultTransitionproperty or by passing it to theViewNavigatorobject’s action functions. - View instances managed by
ViewNavigatorcan be destructed when they are no longer on the top of the stack. This can be controlled with a new property inIViewinterface nameddestructionPolicy. This property has two possible valuesautoandneverthat are also available in theViewDestructionPolicyenum class. DefaultIViewimplementations have this property set toauto.
Using it with Flex (desktop) projects:
Actually this is the feature I’m most excited about. You may wonder why this is since Flex already comes with the ViewStack component and ViewNavigator available in Flex Hero mobile projects. The reason is that the ViewStack doesn’t allow two views to be visible at the same time so this type of nice slide transition is not possible (at least the transition in which two views slide in at the same time, I will blog about this in my next post). And as I mentioned already the Flex Hero ViewNavigator is not available for desktop projects, at least not yet. Of course there is a third option, using state transitions, but it doesn’t come with an API as well thought through as the one in ViewNavigator.
Below you can see it working with Flex (right-click to access the example source code):
In the Main MXML document you can see that ViewNavigator can be treated like any other Flex component. It also has the set of properties that set up the first view and register the ViewNavigatorEvent.VIEW_CHANGING event handler. In the snippet below SampleView is registered as firstView and the viewNumber property of the first view instance is set to 1.
// Main.mxml <?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" xmlns:vn="http://ns.riaspace.com/as3viewnavigator" width="350" height="350" viewSourceURL="http://riaspace.com/examples/as3viewnavigator/flex/srcview/index.html"> <fx:Script> <![CDATA[ import com.riaspace.as3viewnavigator.demo.SampleView; import com.riaspace.as3viewnavigator.events.ViewNavigatorEvent; protected function navigator_viewChangingHandler(event:ViewNavigatorEvent):void { txtTrace.appendText( "action: " + event.action + ", oldView: " + event.oldView + " newView: " + event.newView + "\n" ); } ]]> </fx:Script> <s:VGroup left="5" top="5" right="5" bottom="5"> <vn:ViewNavigator id="navigator" firstView="{SampleView}" firstViewProps="{{viewNumber : 1}}" viewChanging="navigator_viewChangingHandler(event)" width="100%" height="70%" /> <s:Label id="lblTrace" text="Navigator events:" /> <s:TextArea id="txtTrace" width="100%" height="30%" /> </s:VGroup> </s:Application>
The SampleView MXML document extends the View class that comes with as3viewnavigator for Flex. Within the SampleView there are five buttons declared that let you play with ViewNavigator action functions. The code also declares the public viewNumber property that is set by the view that pushed the current view to the top of the stack. The value of the viewNumber property is 1 more than the viewNumber property from the previous view.
// com/riaspace/as3viewnavigator/demo/SampleView.as <?xml version="1.0" encoding="utf-8"?> <vn:View xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" xmlns:vn="http://ns.riaspace.com/as3viewnavigator"> <fx:Script> <![CDATA[ import mx.utils.NameUtil; override public function toString():String { return NameUtil.createUniqueName(this); } ]]> </fx:Script> <fx:Declarations> <fx:Number id="viewNumber" /> </fx:Declarations> <s:Rect width="100%" height="100%"> <s:fill> <s:SolidColor color="#f0f0f0" /> </s:fill> </s:Rect> <s:Label id="lblViewNumber" text="{viewNumber}" fontSize="55" top="10" horizontalCenter="0" /> <s:VGroup bottom="10" horizontalCenter="0"> <s:Button id="btnPushView" label="push view" width="100" click="navigator.pushView(SampleView, {viewNumber : (viewNumber + 1)})" /> <s:Button id="btnPopView" label="pop view" width="100" click="navigator.popView()" /> <s:Button id="btnPopAll" label="pop all" width="100" click="navigator.popAll()" /> <s:Button id="btnPopToFirst" label="pop to first" width="100" click="navigator.popToFirstView()" /> <s:Button id="btnReplace" label="replace" width="100" click="navigator.replaceView(SampleView, {viewNumber : (viewNumber + 1)})" /> </s:VGroup> </vn:View>
Using it with AS3 projects:
The example below shows the AS3 version in action. You can also right-click it to access the full source code.
In this example, the ViewNavigator is instantiated and added as a child of the Main class (the Main class listing is below this paragraph). The ViewNavigator constructor receives two parameters: the class type of the first view (SampleView) to display and an Object with view properties to be set (in this case, this is my custom viewNumber property, which will be displayed in the view label). Before ViewNavigator is added as a child to the Main class it also registers a ViewNavigatorEvent.VIEW_CHANGING event handler that traces out info about ViewNavigator actions. Another thing to note here is that the ViewNavigator size is set explicitly in the layoutComponents function using setSize function. It is important to understand that in this situation ViewNavigator will not auto-size itself anymore to the size of the stage. That is why layoutComponents function is also called by stage Event.RESIZE event handler.
// Main.as package { import com.adobe.viewsource.ViewSource; import com.riaspace.as3viewnavigator.ViewNavigator; import com.riaspace.as3viewnavigator.demo.SampleView; import com.riaspace.as3viewnavigator.events.ViewNavigatorEvent; import fl.controls.TextArea; import flash.display.Sprite; import flash.display.StageAlign; import flash.display.StageScaleMode; import flash.events.Event; [SWF(width="350", height="350", frameRate="30")] public class Main extends Sprite { private var navigator:ViewNavigator; private var txtTrace:TextArea; public function Main() { // Adding source code view ViewSource.addMenuItem(this, "http://riaspace.com/examples/as3viewnavigator/as3/srcview/index.html"); stage.align = StageAlign.TOP_LEFT; stage.scaleMode = StageScaleMode.NO_SCALE; // Adding trace area txtTrace = new TextArea; // Creating instance of ViewNavigator navigator = new ViewNavigator(SampleView, {viewNumber : 1}); // Registering view navigator event handler navigator.addEventListener(ViewNavigatorEvent.VIEW_CHANGING, navigator_viewChangingHandler); // Setting components dimenstions and positions layoutComponents(); // Adding txtTrace component addChild(txtTrace); // Adding navigator to the current sprite addChild(navigator); // Adding resize handler to handle components layout stage.addEventListener(Event.RESIZE, function(event:Event):void { layoutComponents() }); } protected function layoutComponents():void { // Resizing txtTrace component txtTrace.width = stage.stageWidth; // Setting fixed height of txtTrace component txtTrace.height = 60; // Positioning txtTrace component below navigator txtTrace.y = stage.stageHeight - txtTrace.height; // Setting navigator size to be over txtTrace component navigator.setSize(stage.stageWidth, stage.stageHeight - txtTrace.height); } protected function navigator_viewChangingHandler(event:ViewNavigatorEvent):void { txtTrace.appendText( "action: " + event.action + ", oldView: " + event.oldView + " newView: " + event.newView + "\n" ); } } }
The SampleView class extends View, which is a default implementation of the IView interface. Because the View class extends Sprite you can add/remove child DisplayObjects to/from it and work with it as with a standard Sprite. Worth mentioning here is overridden function resize. Doing so allows to scale and layout child elements of the view whenever the owning ViewNavigator size changes.
// com/riaspace/as3viewnavigator/demo/SampleView.as ... override public function resize():void { for (var element:Object in _elements) { var coordinates:Object = _elements[element]; position(DisplayObject(element), coordinates.horizontalCenter, coordinates.verticalCenter); } } ...
as3viewnavigator – ViewNavigator for as3/flash projects
I’m currently working on an application for the BlackBerry PlayBook tablet. The API that comes with the PlayBook SDK is based on pure AS3. Of course I could use Flex Hero for the job but I wanted to try out the “native” stuff that it comes with. My impression so far is really positive and the only thing that I’ve found missing so far was the concept of Views and ViewNavigator that comes with Flex Hero for mobile devices.
That is why I took a bit of time today to create library heavily inspired by ViewNavigator from Flex Hero that I could use for my pure as3/flash projects. The library is available for download here. Also checkout the video below for the details on how to use it.
Just for the reference, to tween the view transitions I used Tweener library that is also used internally by PlayBook API.
Below is the snippet of code that implements the example from the video above, you can also download the project source from here.
package { import com.riaspace.as3viewnavigator.ViewNavigator; import flash.display.Sprite; import flash.display.StageAlign; import flash.display.StageScaleMode; import flash.events.MouseEvent; import flash.text.TextFormat; import flash.text.TextFormatAlign; import qnx.ui.buttons.LabelButton; import qnx.ui.core.Container; import qnx.ui.core.ContainerAlign; import qnx.ui.core.ContainerFlow; import qnx.ui.core.SizeMode; import qnx.ui.core.Spacer; import qnx.ui.text.Label; [SWF(width="600", height="1024", backgroundColor="#FFFFFF", frameRate="30")] public class Main extends Sprite { private var navigator:ViewNavigator; private var viewNumber:int = 0; public function Main() { initializeUI(); } private function initializeUI():void { stage.align = StageAlign.TOP_LEFT; stage.scaleMode = StageScaleMode.NO_SCALE; // Creating instance of ViewNavigator navigator = new ViewNavigator(this); // Pushing first view to the navigator navigator.pushView(createView()); } private function createView():Container { var view:Container = new Container; view.flow = ContainerFlow.VERTICAL; view.align = ContainerAlign.MID; // Incrementing view number viewNumber++; // 20% spacer from the top view.addChild(new Spacer(20)); // Adding label with view number var numLabel:Label = new Label; numLabel.text = viewNumber.toString(); var format:TextFormat = new TextFormat; format.size = 70; format.bold = true; format.align = TextFormatAlign.CENTER; numLabel.format = format; numLabel.size = 100; numLabel.sizeMode = SizeMode.BOTH; view.addChild(numLabel); // 15% spacer between label above and buttons view.addChild(new Spacer(15)); // Adding "push view" button var btn:LabelButton = new LabelButton; btn.label = "push view"; btn.addEventListener(MouseEvent.CLICK, function(event:MouseEvent):void { navigator.pushView(createView()); }); view.addChild(btn); // Adding "pop view" button btn = new LabelButton; btn.label = "pop view"; btn.addEventListener(MouseEvent.CLICK, function(event:MouseEvent):void { navigator.popView(); }); view.addChild(btn); // Adding "pop all" button btn = new LabelButton; btn.label = "pop all"; btn.addEventListener(MouseEvent.CLICK, function(event:MouseEvent):void { navigator.popAll(); }); view.addChild(btn); // Adding "pop to first button" button btn = new LabelButton; btn.label = "pop to first"; btn.addEventListener(MouseEvent.CLICK, function(event:MouseEvent):void { navigator.popToFirstView(); }); view.addChild(btn); // Adding "replace" button btn = new LabelButton; btn.label = "replace"; btn.addEventListener(MouseEvent.CLICK, function(event:MouseEvent):void { navigator.replaceView(createView()); }); view.addChild(btn); return view; } } }
UnFramework – or how to work without any frameworks
Those who know me or at least subscribe to my blog know that I’m a big fan of Flex/AS3 frameworks. At this year’s Adobe MAX conference I even had my own session where I covered five major DI frameworks. Usually these frameworks provide a lot of productivity features and helpers like: IoC/DI, Event/Messaging bus, implementation of some architectural or design patterns (MVC, Command…), and many others. But what happens if we can’t or don’t want to use any of these frameworks?
Swiz 1.0 Command pattern API explained
As you may know the Swiz team has released RC2 of the upcoming 1.0 version. Among many improvements and bugfixes there is one new feature that brings a built-in command pattern to Swiz. As part of my prep work for Adobe MAX where I will be speaking about AS3/Flex Frameworks I wanted to investigate it in more depth. As you can read in the Swiz docs, this implementation borrows heavily from the RobotLegs framework, which I will be also covering together with Parsley. This approach is really clean and simple but to be honest I kinda hope that it will evolve in future releases to be more metadata-driven, which is actually what Swiz is all about
In the example below you can see it in action (right-click to view the full source code).
So how do we get started?
If, when you read this post, Swiz is still in RC2, then you will need to grab the latest source code from github and build it yourself, the released RC2 has some quirks in regards to its command pattern implementation.
The first thing you do is create a SaveUserCommand class that implements the IEventAwareCommand interface and has one execute function. Obviously this is the function that will implement the command logic. It doesn’t accept any parameters, so if you need any you should provide them by injection. UPDATE 23.09.2010: Triggering event is available through event setter function when you implement IEventAwareCommand instead of ICommand.
package com.riaspace.max.swiz.commands { import com.riaspace.max.swiz.events.UserEvent; import flash.events.Event; import mx.controls.Alert; import org.swizframework.utils.commands.IEventAwareCommand; public class SaveUserCommand implements IEventAwareCommand { private var _event:UserEvent; public function set event(value:Event):void { _event = value as UserEvent; } public function execute():void { Alert.show("SaveUserCommand executed, userName: " + _event.userName); } } }
Next you can map/configure our command using a MyCommands class that extends the Swiz specific CommandMap. Just a hint here for the Swiz team that it would be cool to have the ability to configure commands directly in BeanProvider in future releases
package com.riaspace.swiz.configs { import com.riaspace.swiz.commands.SaveUserCommand; import com.riaspace.swiz.events.UserEvent; import org.swizframework.utils.commands.CommandMap; public class MyCommands extends CommandMap { override protected function mapCommands():void { // Mapping UserEvent.SAVE to SaveUserCommand class mapCommand(UserEvent.SAVE, SaveUserCommand, UserEvent, false); } } }
Now you can instantiate the MyCommands class in the BeanProvider like any other bean:
<?xml version="1.0" encoding="utf-8"?> <swiz:BeanProvider xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:swiz="http://swiz.swizframework.org" xmlns:commands="org.swizframework.utils.commands.*" xmlns:configs="com.riaspace.swiz.configs.*"> <fx:Script> <![CDATA[ import com.riaspace.swiz.models.presentation.MainPM; ]]> </fx:Script> <fx:Declarations> <configs:MyCommands /> <swiz:Prototype type="{MainPM}" /> </fx:Declarations> </swiz:BeanProvider>
At last you can dispatch the UserEvent.SAVE event in your PM class and the SaveUserCommand.execute will be called.
package com.riaspace.swiz.models.presentation { import com.riaspace.swiz.events.UserEvent; import flash.events.IEventDispatcher; public class MainPM { [Dispatcher] public var dispatcher:IEventDispatcher; public function btnExecuteCommand_clickHandler():void { dispatcher.dispatchEvent(new UserEvent(UserEvent.SAVE, "John")); } } }
