If anyone has used Minimal Components by Keith Peters you know what a great set of componets they are. The only knock against them was the fact they could not be skinned. Until now.
In order to make the components more flexible from a visual standpoint yet retain the minimal footprint I have developed a basic set of classes for drawing shapes and fills and the required logic to handle skinning was added. If you have worked with Flex 4 or Degrafa it should be quite obvious, after looking at the source code, how the components and skins interact and how skins are created. Using either programmatic (ie drawing api) or embedded images you can now easily skin the Minimal Components to your heart's desire.
The demo has three sets of the same components. The first set uses the standard components. The second set is skinned with programmatic skins and the third uses embedded pngs. This demo is super light, even with embedded graphics it weights in at 52kb, compare that to well over 500kb for a comparable Flex app.
The main push to add skinning was Adobe's entrance into the mobile development space. Being involved in the pre release programs for the iPhone and Android packagers it was quickly apparent to any Flex developer involved that Flex is totally not suitable for mobile app development. Note that I said Flex, not Flash. It's just too heavy and processor intensive. This posses a huge dilema for developers accustomed to having a good set of UI components to build with, for now there is nothing to build with. Components would need to be built from scratch. That's a huge non starter for most developers.
Adobe is working to address this with the Slider framework however until that is ready for showtime Flex and Flash developers wanting a decent component set to build mobile apps with are left hung out to dry. Minimal Components seemed like a perfect fit. There are a lot of them, 32 by my count, they are very lightweight and very efficient (all a testament to Keith's skill). The only thing they needed was an easy way to skin them and to separate the view from the core component logic. That's were I focused my energy.
They are still a work in progress. All the necessary work to handle skinning and associating components and skins has been done. Now the work involves refactoring each component (creating a default skin and removing the drawing logic from the component). Currently the Label, PushButton, Text, HSlider and VSlider have been done (as you can see in the demo). All the other components will get converted. Once all the components are skinnable the next major step is adding gesture support.
If you would like to try out the new skinnable version you can find the source code on GitHub. These are still alpha so I'm sure some issues will be uncovered however I want to get this out in the public domain, especially for other Flex and Flash mobile app devs.
Try them out and let me know what you think.
While digging around looking for some info on Keith Peters Minimal Comps I stumbled across a great post by Ryan Campbell on creating pure Actionscript projects using MXML. Actionscript projects using MXML??? yes that's right. Using MXML markup you can create classes without all the Flex overhead. This means you get the benefit of clean easy to read MXML without the bulk of Flex. I will admit, I was completely blown away. I love programming in Flex, I find it much easier and quicker to layout components and views using MXML but I'm often conflicted when I factor in the size advantage a plain Actionscript project has over a Flex project. Now you can have the best of both worlds.
Here is what the mxml looks like.
<?xml version="1.0" encoding="utf-8"?>
<comp:Container xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:comp="com.dgrigg.components.*"
xmlns:text="flash.text.*"
width="250" height="200"
color="0xdddddd">
<fx:Script>
<![CDATA[
[Bindable]
public var text:String = 'Click block to change color';
private function onClick(event:MouseEvent):void
{
var target:Component = event.target as Component
target.color = Math.random()* 16581375;
text = 'Color: #' + target.color.toString(16);
}
]]>
</fx:Script>
<text:TextField id="tf"
x="20" width="200" height="200"
text="{text}"/>
<comp:Component id="comp1"
x="20" y="20" width="200" height="20"
click="onClick(event)"/>
<comp:Component id="comp2"
x="20" y="50" width="200" height="40"
click="onClick(event)"/>
<comp:Component id="comp3"
x="20" y="100" width="200" height="60"
click="onClick(event)"/>
</comp:Container>
I looks just like a Flex MXML class but when compiled it's 12kb vs 532kb (debug version) and 8kb vs 235kb (non-debug version). Wow. If I add the [Bindable] tag, as you can see in the example it adds about 4-6 kb to the non Flex version.
Creating a project to do this is super easy. In Flash Builder (Flex Builder) create a new AS3 Project. After the setup is done
xmlns:fx="http://ns.adobe.com/mxml/2009"
One of the really nice features of coding this way is you can setup event listeners in the MXML just like in Flex, you don't need to type out addEventListener(onEvent, Event.TYPE) blah blah each time.
As I start working on some projects using this method I'm sure I will be posting some more information. The next step is building out a full blown app with RobotLegs and hopefully Degrafa for the skinning.
Sometimes when creating a web based Flex application you want the background to be transparent or semi-transparent. In Flex 3 this involved two steps, setting the 'backgroundGradientAlphas' property on the mx:Application to [0,0] or something less than 1 and setting the 'wmode' on the swf to 'transparent'. Now with Flex 4 (Spark) it's not quite so easy, there is no 'backgroundGradientAlphas' style on the s:Application.
If you want background alpha on the new Spark Application component you need to create a custom skin and a style to the spark:Application. It's surprisingly easy and I actually like this method because it gives the developer much more freedom in how they would like to implement background transparency.
Step 1: modify the default application. Add a new style property using the fx:Metadata tags and tell the application to use the new skin class you are about to create with the 'skinClass' attribute.
<?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"
skinClass="com.dgrigg.skins.ApplicationSkin"
backgroundColor="0xFFFFFF"
backgroundAlpha="0"
width="100%"
height="100%">
<fx:Metadata>
[Style(name="backgroundAlpha",type="Number",default="0")]
</fx:Metadata>
</s:Application>
Step 2: set the new 'backgroundAlpha' style value to whatever you want in the s:Application declaration using the 'backgroundAlpha' attribute (see above).
Step 3: create a new version of the default spark.skins.spark.ApplicationSkin class and change the following section from this:
<s:Rect id="backgroundRect" left="0" right="0" top="0" bottom="0" >
<s:fill>
<s:SolidColor color="{getStyle('backgroundColor')}" />
</s:fill>
</s:Rect>
to this:
<s:Rect id="backgroundRect" left="0" right="0" top="0" bottom="0" >
<s:fill>
<s:SolidColor color="{getStyle('backgroundColor')}"
alpha="{getStyle('backgroundAlpha')}" />
</s:fill>
</s:Rect>
And remember to set the wmode to transparent on object/embed tag. The great part about using a custom skin is you are free to implement a background alpha however you wish, you can do a plain alpha fill, or you could do something more exotic like a radial or linear alpha fill.
The release of Flash Builder 4 and the new Spark components means most Flex developers will be going through the process of discovering what has changed from Flex 3 to Flex 4. For the most part the changes are pretty well documented and with a little trial and error things that used to work and now don't can be easily adjusted to work again. Over the next few months as I work on a few projects using Flash Builder 4 and Flex 4 with the new Spark components I will be sharing my experiences, the tricks I learn and how to avoid the pitfalls I will undoubtably find myself in.
One of the first pitfalls I have run across is using the MX navigator containers (ie ViewStack, TabNavigator, etc). The Spark component set has no corresponding components and due to differences in the Spark containers you can not simply add a Spark group to a navigator container like you can an MX container. You need to wrap the Spark component(s) in a NavigatorContent instance first. It's a little cumbersome but I have found that if the view you are creating will only be used in a navigator container then it's easiest to simply have you component/view extend the NavigatorContent class.
There are some basic demos here and here on how to use the NavigatorContent in a navigation container. The problem I ran into was with the creation policy. As you likely know navigation containers have a creationPolicy property that determines when the children get created. Ideally you use the default setting which means the children only get created as needed. The issue I had was in Flex 3 you could have a creationComplete event listener on the navigator children and it would only fire once the container was displayed. In the function called from the event you could access any of the container's children as you knew at that point they had all been created.
Unfortunately in Flex 4 with the Spark components this no longer holds true. When you use the NavigatorContent class the creationComplete event is dispatched immediately when the navigation container (ie ViewStack is added to the stage) however if the creationPolicy is not set to all, the actual children on the NavigatorContent have not yet been created and you end up with RTE's when referencing the children. To prevent this from happening you need to listener to a new event, the 'contentCreationComplete' event which only fires once the NavigatorContent becomes visible.
You can quickly see in the demo below how the two differ (right click to view the source).
The MX Views only fire the 'creationComplete' when the view is displayed. At that point any children of the view can be accessed. The Spark views however, all fire the 'creationComplete' when they are first added to the ViewStack. At that point accessing any child object of the view will throw an error. It's after the 'contentCreationComplete' that you can access children of the Spark view. It's a little semantic difference, but it's a huge headache the first time you run across it.
If you live in Massachusetts and are concerned about the education system you should visit Standforchildren.org . It's not very often I work with non-profit organizations however this was a really neat project to be involved with. Stand For Children wanted to get the message across to legislators in Massachusetts and across the US that childrens' needs and rights regarding public education need to be heard.
The team at Stand For Children wanted people to actively create, post and share virtual signs about their stand for the public education system. Brian from the The ID Corp came up with a great concept and using some Flash and PHP magic I was able to execute it.
Living in Canada it's an entirely different situation with public education. I was shocked to find out just how different (and not for the better) the US public education system is. Stand for Children has a great team and I hope this campaign and more like it will help pave the way for a more promising future for America's youth.
So go ahead. Take a stand.
Derrick Grigg is a Rich Internet Application (RIA) freelance contractor based in Toronto, Canada. He specializes in architecting and developing applications using a variety of technologies, most notably Flash, Flex and Coldfusion.