Skip to content
January 23, 2012 / Daniel Freeman

Why developers are using MadComponents

MadComponents is a free open-source UI framework for Adobe AIR mobile applications.  It’s popularity seems to be founded on the advantages it offers over using Flex in terms of file size, performance, and ease of development.

Here’s some of the feedback and endorsements I’ve received from developers…

“I started playing with Mad Component and am banging my head against the wall for having wasted so much time with FlashBuilder! …It will take less than half the time to create the same app now” [R]

“After months of working with the Flex mobile components and having some performance issues. I finally took a Saturday to learn about your framework and compare the performance with Flex. Oh my god. It’s unbelievably good, well documented and easy to use. Straight AS3 is the way to go.”

“I’m glad I found MadComponents. I think I’ve pretty much given up on Flex for mobile at this point. I’m continuously disappointed with the performance on my IPad.” [K]

“To be honest, I’ve never done anything in Flex beyond the tutorials. It’s just all too bloated… MadComponents is wonderful – I making big use of it in a large and complex multi-platform app.” [J]

I got full screen video from camera running… more or less same code built with Flex – start the app on iPhone – get splash screen – get empty screen for maybe 2 – 3 seconds then get video. With MCs pure ActionScript – start the app on the iPhone – get splash screen
- IMMEDIATELY get video – there is a MAJOR performance increase.” [RT]

“Thank you! Thank you! These are the components that really should’ve been included in the standard library for AIR for Mobile in the first place!” [T]

“This is all very promising, as I have been stymied by the atrocious performance of Flex on mobile devices… You’ve really stepped out into the express lane by offering this library. There are very few usable libraries like this and I imagine demand will be high….Thanks for all the work you’ve put into this.” [RH]

“Adobe – this is the component set that should have been part of AIR/mobile from the beginning.” [J]

“I want to congratulate you on MadComponents – it has certainly made my life easier for cross-platform development!” [D]

“Awesome Work Daniel!!! Thank you soooooo much for for this and sharing it. I’m working on a project now and was banging my head with Flex’s MXML. Love this!!!” [M]

“This is excellent work. Evaluating now for our apps. Looks like just what I needed. Flex just can’t cut it for our app (and I’ve been doing AS and Flex for a *long* time before I make that statement).” [C]

“You have done a terrifIc job. Mad Components is by far more complete and look really better that Flex Components.” [MB]

“For months we were hooing and hawing about what technology to use for the next app that we were building. We looked at HTML 5, JQ Mobile and PhoneGap for a little while and this was great, except for some reason none of our early tests would consistently work in the different environments (iOS, Android, etc) … Flex can do quite well but we have had issues with glitchy animation… After a little bit of searching we came across the Mad Components library… the application was able to be developed in a much shorter time thanks to MadComponents.” [CULT]

“Thanks for all your efforts with MAD Components – the prototypes I’ve been able to build and deploy across the devices has definitely helped influence the investor’s decision.” [RT]

“I just started using mad components and I love it and it looks like it will replace Flex Hero in my next app.” [RF]

January 12, 2012 / Daniel Freeman

Extending MadComponents

I previously blogged about how to incorporate components from other libraries into a MadComponents layout.  I showed how MadComponents could be mixed with MinimalComps and as3Flobile components.  But the approach I used to be applied to any component library, or components that you write yourself.  (Provided the class constructors have no arguments).

There are two other techniques as well, for including non-MadComponent stuff into a layout.  So I’ll describe them here.

Before I go into that, if you haven’t heard about MadComponents before – it’s a popular free-open-source framework for AIR mobile User Interfaces.  It is significantly more lightweight than the bloated Flex mobile framework, and many users have reported much, MUCH, better performance than Flex.  You can express a layout in XML (incurring NO decline in performance), or you can incorporate the components into standard Pure-AS3 code.  There’s plenty of information about them on this blog, and the code site has lots of examples.  Please join the new Facebook Page – to get up-to date news and discussion.

Anyway, as I was saying, there are two further ways to incorporate new components into MadComponents.

Placeholder Technique

This is where you define an empty placeholder within the layout, and then attach (addChild) a component to the placeholder.  An <image> makes a good placeholder, because you can specify a size for it.

example:

<vertical>
        <button>one</button>
        <image id=”placeholder”>120,90</image>
        <switch/>
</vertical>
 
var placeholder:UIImage = UIImage(UI.findViewById(“placeholder”));
placeHolder.addChild(myComponent);
 

A placeholder can also define a window to StageVideo, or Stage3D behind the MadComponents layout.

UI.extend() Technique

UI.extend() is a static method to add new components to MadComponents.  ExtendedMadness uses it to add its extra components to the MadComponents core.  The constructor parameters of an extended component must conform to this pattern:

public class MyNewComponent extends MadSprite {
 
        public function MyNewComponent(screen:Sprite, xml:XML, attributes:Attributes) {
        screen.addChild(this);

Where screen is the parent container component, xml is the layout xml branch, and attributes contains information about how to lay the component out (although you don’t need to worry about this for a simple component).

Having defined your new component, (or sub-classing an existing MadComponents class), you can add it  to MadComponents like this:-

UI.extend(["newThing"],[MyNewComponent]);

Once you’ve done this, <newThing> is a defined tag that you can use in a MadComponents layout.  For example:-

<vertical>
         <button/>
         <newThing … etc….

Suppose your component needs to be re-rendered, or laid out differently on orientation change.  Landscape <-> Portrait.  Then you must implement the IContainerUI interface, and write each of its methods, including layout(), which is what will be called on orientation change.  Now your component must conform to this pattern:-

public class MyNewComponent extends Sprite implements IContainerUI {
        public function MyNewComponent(screen:Sprite, xml:XML, attributes:Attributes) {
        screen.addChild(this);
 
.
.
.
public function layout(attributes:Attributes):void {
        // Re-layout component
}

You’ll also need to implement the other methods of IContainerUI.  It’s best to look at examples within extendedMadness.

 

Contribute to ExtendedMadness

While I kept the development of MadComponents quite close to my chest, because I didn’t want to compromise its lightweight design.  But if anyone else has inspiration and vision to contribute to ExtendedMadness, then I’d like to open up the project to other contributors.

December 19, 2011 / Daniel Freeman

Free AIR book + MadComponents Facebook page

Some of you will know that I’ve have the urge to write an Adobe AIR for mobile book, and I’ve been trying to get a publisher interested.  I’ve had no success with that, and most publishers are feeling pretty skittish in regards to Adobe topics nowadays.  But, it’s likely that I’m going to go ahead anyway and write the book.  There is currently no AIR book that addresses the subject in the way I have in mind, and self-publication, is in itself, an interesting frontier for me.  Electronic standards such as ePub and Mobi have empowered technologically-savvy authors to take matters into their own hands like never before.

Let’s look at the maths.  If I was to go through a publisher, and sell my book for $50.  I would likely receive $7.  If I publish a $10 iBook version for iPad myself, I would still receive $7.  And everyone who purchases my book saves $40.

Of course, I’d need to factor-in paid marketing costs, because I’d have to do that myself too.  But my target market is pretty well defined, so I’m asking myself – are technical book publishers obsolete?

Obsolete or not, they’re certainly not worth the effort.  I’ve gone to so much trouble chasing around after publishers, to no avail.  And writing so many detailed book proposal documents. (Every publisher has their own unique format for these).  My energy would have been much better spent, just getting on with it, and writing the book!

It will be a little while before I have anything to show you all – ( depending on my freelance obligations ) – so stay tuned, and keep following this blog.

Joseph Labracque has faired somewhat better with the orthodox publishing process than I have.  He’s struck a deal to give his book away absolutely free. “What’s new in Adobe AIR 3″ is available from O’Reilly’s website.  ( I noticed there are other free books there too ).

I’ve got my copy.  It’s pretty concise and lightweight.  But a handy bare-bones description of everything new in AIR.  A great free asset for AIR developers – download your copy NOW.

MadComponents Facebook Page

I’ve created a Facebook page for MadComponents.  With so many developers using it now, I don’t always have the time to respond promptly to questions on this blog.  But everyone can contribute equally to the facebook forum, and help others in the community.  Or discuss anything MadComponents and/or AIR related.

Click to join this group, and I’ll add you ASAP.

MadComponents performance tweaks

There are a couple of performance tweaks in the latest version.  Previously all UI views were initialised on application launch.  Now, there’s a lazyRender attribute for pages, tabPages, navigation, and navigationPages, so that pages are rendered lazily.  When you first switch to that page.

I know that some developers may think this feature is overdue.  But for most applications, it’s not such a big deal.  If you’ve tried MadComponents, you’ll notice that a mobile app starts up much faster, and takes much less memory than a Flex mobile app, even though Flex employs lazy page rendering.

But now you can tweak the performance of MadComponents even further, and write something like:-

<tabPages lazyRender="true">
   {FIRST_PAGE}
   <vertical id="page2">
  ..etc...etc...

Pages within the tabView will be loaded and rendered as they’re viewed.  Not on application launch.  But this means that you can’t do UI.findViewById(), on views that haven’t yet loaded.  So there’s an event you can listen for that tells you when a particular page has loaded.

var page2:UIForm = UIForm(UI.findViewById("page2"));
var page2Container:UIForm = UIForm(page2.parent);
page2Container.addEventListener(UIForm.LOADED, page2LoadHandler);

Another performance tweak is cached ImageLoaders.

<imageLoader cache="true" url="....

Now, once the image has been loaded once, subsequent loads of the same image will load from the local cache.

There are static methods to clear the cache under program control:-

UIImageLoader.clearCache(url); //clears a specific url cache
UIImageLoader.clearCache();  //clears entire cache
December 7, 2011 / Daniel Freeman

ExtendedMadness now Open-Source

ExtendedMadness is a Pure ActionScript framework and UI component library for mobile applications.  It’s based on MadComponents at the core, and although it contains more UI components, it is still going to result in much more lightweight mobile applications than Flex.  ExtendedMadness now contains a SplitView for tablet UIs, Android-style tab buttons, and a star-rating component.

You can find the sourcecode here, and plenty of examples here.  Download the .swc from here.

I’ve blogged about some of the components before.  Charts, SegmentedControls, etc.. ( <svg> has been depreciated and removed )  So here’s a quick rundown about what’s left:-

CheckBoxes and RadioButtons

CheckBoxes and RadioButtons now have a built in label, so you utilise them like this:-

<checkBox>Text Here</checkBox>
<checkBox><font color="#FF9933">Text Here</font></checkBox>
<checkBox><font color="#FF9933"/>Text Here</checkBox>
<radioButton><font color="#FF9933"/>Text Here</radioButton>

Tab Pages Top

These are Android-style tab buttons at the top of the page.  You use them exactly as you would the MadComponents <tabPages> container.

<tabPagesTop id="tabs" stageColour="#333333">
   {PAGE}
   {SCROLLXY}
   {LIST}
</tabPagesTop>;
var tabPages:UITabPagesTop = UITabPagesTop(UI.findViewById("tabs"));
tabPages.setTab(0, "U.I.", OPTIONS);
tabPages.setTab(1, "scrollXY", ZOOMIN);
tabPages.setTab(2, "List", ARROW);

Star Rating

<starRating id="stars" value="3" background="#999999,#FFFFFF"/>
<starRating value="2" alt="true" background="#999999,#FFFFFF"/>
_stars = UIStarRating(UI.findViewById("stars"));
_stars.addEventListener(Event.CHANGE,starsChanged);
protected function starsChanged(event:Event):void {
     trace(_stars.value);
}

ScrollXY

ScrollXY was originally part of core MadComponents, but I moved it into ExtendedMadness to make room for more mainstream stuff.  ScrollXY allows you to scroll in both directions, and double-tap to magnify and reduce the contents.  The tapToScale attributes specifies the magnification, and notice how we declare the width and height of the contents.

<scrollXY tapToScale="3.0" stageColour="#666666"
             scrollBarColour="#FFFFFF" width="480" height="640" border="false">
   <image>
      {getQualifiedClassName(THAILAND)}
   </image>
</scrollXY>;

There’s an example on the code site, here.

Split View

This is an essential container for tablet UIs.  It is the tablet equivalent to a navigation container, where both the list and the detail page are shown in landscape orientation.  In portrait orientation, the list is inside a drop down menu.

There’s a simple example of the split view here.

Tree Navigation

This is a list component that was originally part of MadComponents, but overflowed into ExtendedMadness to make space.  The concept of tree navigation, is to turn hierarchical data into hierarchical nested lists.  There are a couple of examples of using this component here and here.

 

 

DataGrid

For displaying tabular data.  You can make it editable by using an editable=”true” attribute, but that is only recommended for desktop use, not mobile, as the cells are quite small (and difficult to poke with a finger).  But fine for displaying un-editable data on mobile.

<dataGrid colour="#999999" background="#888899,#EEEEFF,#DDDDEE">
   <widths>30,30,40</widths>
   <header>one,two,three</header>
   <data>
       <row>1,2,3</row>
       <row>4,5,6</row>
       <row>7,8,9</row>
       <row>2,7,5</row>
       <row>1,2,3</row>
       <row>4,5,6</row>
       <row>7,8,9</row>
       <row>2,7,5</row>
   </data>
</dataGrid>

There’s a datagrid example here.

ScrollBars

There are three desktop-style scrollbar panels.  <scrollBarVertical>, <scrollBarHorizontal>, and <scrollBarPanel>.  A <scrollBarPanel> has both a side and bottom scroll bar.  Like scrollXY, you must specify a width and a height for the contents.

December 5, 2011 / Daniel Freeman

10 new MadComponents features

I haven’t had the time to blog about MadComponents lately.  But I’ve still been developing and refining it whenever I get a few spare moments. ( MadComponents is an increasingly popular, open-source, powerful yet lightweight, pure-actionscript mobile app framework. )  You’ll find the latest version here.  I’ve implemented some new features in response to developer requests.  But most were driven by perfectionism.  At this stage of development, having achieved maturity and stability with the framework, the latest updates and features are all about the finer details.  (So if this your first encounter with MadComponents, it is better to start with a more general explanation.)

So here’s a rundown of 10 new features:-

1. <navigationPages>

To keep MadComponents lightweight, I’d decided not to add any new components to it.  But <navigationPages> implements such a common requirement, that I moved <scrollXY> out of the library to make room for it.

Suppose we have a navigation based application, with a list view and a detail page.  Let’s assume each list row, loads in a different detail page.  Clicking on the first list row, shows the first detail page, clicking on the second list row, shows the second detail page, and so on.  This is such a common UI pattern, that I’d already written this example showing developers how to do it.

Now <navigationPages> makes this UI pattern even easier, with no extra programming required.  Simply arrange the layout XML like this:-

<navigationPages>
   {LIST}
   {PAGE0}
   {PAGE1}
   {PAGE2}
</navigationPages>

There’s an example on the Google code site. <navigationPages> can be nested. For cascading menus, see the example here.

 

2. Alternative <switch> style

If you write <switch alt=”true”/>, it renders a curved appearance for the switch.

 

3. <model> parse attribute

The <model> tag is one of MadComponent’s most powerful features.  It enables the user interface to communicate with a web server, and fetch data using XML, JSON, or AMF.  Suppose we’re writing an RSS reader.

The schema for RSS XML data looks like this:-

<rss>
   <channel>
      <item>
         data in here
      </item>
      <item>
          data in here
      </item>
etc... etc...

We’re interested in the XML information inside <item> packets.  Notice that to get to <item>, we first need to go through <rss>, and <channel>.  For each list row, we just want <title>, <pubDate>, and <description> for our app.  We can describe the schema more concisely like this:-

<rss>
   <channel>
      <item>
         <title/>
         <pubDate/>
         <description/>
      </item>
   </channel>
</rss>

So let’s put all the pieces together, and show how the list is made.

<list autoLayout="true">

<model url="http://rss.cnn.com/rss.edition.rss" action="loadXML">
      <rss>
         <channel>
            <item>
                <title/>
                <pubDate/>
                <description/>
            </item>
         </channel>
     </rss>
   </model>

   <vertical alignH="fill">
      <label id="title"/>
      <label id="pubDate"/>
      <label id="description"/>
   </vertical>

</list>

Notice that within the model tag, we’ve described both the url of the rss feed, and an action.  loadXML.  Within the list itself, we’ve specified autoLayout=”true”.  This is because each row of our list will be a different height, depending on how much text it contains.

The XML above may look simple, but in fact, it can be simplified even further.  This is where the parse attribute comes in.  We don’t have to write the schema out in full.  We can just write this:-

<list autoLayout="true">
   <model url="http://rss.cnn.com/rss.edition.rss" action="loadXML" parse="rss.channel.item"/>
      <vertical alignH="fill">
         <label id="title"/>
         <label id="pubDate"/>
         <label id="description"/>
      </vertical>
</list>

(Note: that the model path attribute is now depreciated).

4. parse wildcards

When parsing a JSON feed, if you leave out a tag name within a parse attribute, that missing name is treated as a wildcard, and it will match any key name during the parse.

Why is this useful?

Take a look at some JSON data for a twitter trends feed ( http://api.twitter.com/1/trends/daily.json ):-

{"trends":{"2011-12-03 15:20":[{"name":"#TwoThingsThatNeverMix","query":"#TwoThingsThatNeverMix"...

Notice "2011-12-03 15:20" ?  That's a date stamp.  It is also a key value that will be different every time.  So we can't write a schema for this feed, because it's always going to change.  In my opinion, a Twitter feed shouldn't have been designed like this, with a changing key value.  But we can solve this problem and employ a wildcard.  parse="trends.".  The dot at the end, means that the next key value to matched to whatever comes next, so the date stamp is skipped.

( The complete twitter trends example is here )

5. Helper methods

The model class contains two static helper methods that can be useful when dealing with online data:-

Model.queryString()  Will remove extended characters from a string, and then escape it, converting it into a valid URL query string.

Model.htmlDecode()  Will convert special XML encodings such as &amp; to their corresponding characters.

6. XML data

We can specify XML data for multiple fields.  For example:-

<data>
   <item firstname="Fred" lastname="Bloggs"/>
   <item firstname="Sarah" lastname="Wilson"/>
   <item firstname="Peter" lastname="Potter"/>
</data>

(Previously, we could only specify a single field for each XML item ).

7. Concatenating Fields

Let's suppose you were connected to an XML feed supplying firstnames, and surnames, and you wish to display these in a list.  Concatenate the firstname, to the surname, with a space between.  We can accomplish this by mapping both fields to the same component.  For a list without a custom renderer, the default UILabel has an id named "label".  Here's an example:-

<list>
   <model url={URL} action="loadXML">
      <root>
         <item>
            <firstname>label</firstname>
            <surname>label</surname>
         </item>
      </root>
   </model>
</list>

 

8. loadXML(), loadJSON(), and loadAMF() API changes

I haven't got around to updating the class documentation yet, but the Model APIs all have an extra optional parameter that allows you to set further options for the URLRequest or NetConnection.  One possible use of this parameter is the ability to set log-in details for a secure web site.

Here are the method headings:-

public function loadXML(url:String = "", request:URLRequest = null):void
public function loadJSON(url:String = "", request:URLRequest = null):void
public function loadAMF(url:String = "", service:String = "", parameters:Array = null, netConnection:NetConnection = null):void

9. sortBy and sortMode attributes

The list sortBy attribute now allows a list to be sorted by more than one field.  For example:-

<list sortBy="surname,firstname">

The sortMode parameter allows each sortBy field to be sorted according to different criteria.  For example:-

<list sortBy="date" sortMode={[Array.DESCENDING | Array.NUMERIC]}/>
<list sortBy="surname,firstname" sortMode={[0,Array.CASEINSENSITIVE]}/>

( 0 is the default mode.  Ascending )

10. Cascading Styles

I’ve had a few queries lately regarding styling.  This isn’t really a new feature, and it is really more of an ActionScript trick than a feature of MadComponents.

MadComponents are very customisable using the colour and background attributes. Also the skin attribute for a button. For many components (Button, Label, Lists, Picker, etc.), you can also specify the text style as HTML. Eg. <font size=”20″ color=”#CCCCFF”/>.

Other attributes such as the size (width, height) and its positioning (alignH, alignV, gapH, gapV) aren’t considered as styles, because they’re more to do with the layout, which will adapt to the screen size of the device.

Define all the styles in XML at the top, or in a Styles class. For example:-

public static const LIGHT_BLUE:XML = <font size=”20″ color=”#FFCCCC”/>;
public static const BUTTON_STYLE:String = “#9999CC,#EEEEFF,#EEFFEE,40″;

Wherever you need to apply styles, you do this kind of thing:-

public static const BUTTON:XML =
   <button background={MyStylesClass.BUTTON_STYLE}/>
      {MyStylesClass.LIGHT_BLUE}Press Me
   </button>;

(Assuming you’ve defined all your styles in MyStylesClass)

Postscript: A couple more features…

I’ve also added a backToExit attribute to <navigation>, so that the Android back button will close the application if you’re on the first page.

<navigation backToExit="true">

In version 0.6.7, I’ve added an includeInLayout property to components.  Used in conjunction with visible, this can make a component invisible, but also collapse the UI around it.  But, you need to refresh the layout for it to take effect (for which autoLayout for the container must be true).  For example:-

<vertical id="form" autoLayout="true">
   <button>button0</button>
   <button id="button1">button1</button>
   <button>button2</button>
</vertical>
var button1:UIButton = UIButton(UI.findViewById("button1"));
var form:UIForm = UIForm(UI.findViewById("form"));
button1.includeInLayout = button1.visible = false;
form.data = {};  // forces re-render due to autoLayout="true"

I decided also to provide a helper method of UIForm to simplify the above:-

var form:UIForm = UIForm(UI.findViewById("form"));
form.includeComponent("button1",false); // true = include, false = remove

( You don’t need autoLayout=”true” for this helper method )

 

 

Help Spread the Word or Get Involved

I’ve contributed MadComponents freely to the AIR Mobile developer community.  Please give something back if you can.  There’s lots of things I need help with now.  For example:-

1. Always report any bugs or shortcomings you come across.  I can usually remedy these quickly.

2. Let me know what you do with MadComponents.  If you use it to build enterprise apps, or make something for the app-store – let me know.  I’d like to showcase success stories to promote this framework.

3. Please help spread the word about MadComponents and ExtendedMadness, by blogging and twittering.

4. It would be great if you could contribute more examples and tutorials, or even just talk about these libraries and what they can do.

5. People have asked if I can make an interactive web-based MadComponents (kitchen-sink) demo.  Does anyone have the time to make and host one of these?

6. Can someone blog about using MadComponents with an MVC framework such as RobotLegs?  Or write some tutorials?

7. There may be a problem with AMF.  I’m not sure I have the AMF expertise to sort it out.  If you take a look at these discussions in the comments, perhaps you can investigate the issue, and suggest a patch, or workaround for this problem?  Or maybe we need someone to write more AMF tutorials.

8. I pointed the way about how to make Flex wrappers for MadComponents.  But I’m much more into the pure-actionscript approach myself.  Does anyone want to pick up the Flex wrappers, improve, extend, and maintain them?

9. How about applying the lightweight MXML technique to the Flex wrappers?

http://dgrigg.com/blog/2010/04/28/alpha-release-of-skinnable-minimal-components/

http://dgrigg.com/blog/2010/04/12/when-flex-goes-on-a-slimfast-diet/

November 13, 2011 / Daniel Freeman

Farewell Flex. Good riddance.

It’s been an unsettling and uncertain week.

Even before the news broke – I’d felt the winds of change.   Like the icy chill of a company changing direction, without the slightest regard for its loyal and dedicated developer community.

The Flex Evangelists were all suddenly blogging about PhoneGap instead.

For months, I’ve found it impossible to get publishers interested in an AIR mobile book I’m inspired to write.  ”No interest in AIR”, they would say.

Christian Cantrell blogged about porting AIR applications to HTML.

But despite the mixed messages, AIR seems to be safe – we think.

It’s healthy for a company to adapt to become more competitive in the face of new opportunities.  It should be a positive thing, shouldn’t it?

That’s not how the message was conveyed.  If it was Adobe’s intention to generate as much FUD and negative speculation as possible – they couldn’t have done a better job.

I remember that Macromedia had a better understanding, and respect, for the developer community.

Last month, I was involved in a mobile developer conference.  Just a small affair.  200 people.  Mostly new to the mobile arena, and mostly interested in developing enterprise apps, not public apps on an app store.  As a result of my afternoon workshop, many of these developers went away VERY interested in Adobe AIR and MadComponents.  Some have already adopted it for their projects.

I invited Adobe to come along to my conference and give some mobile-related presentations.  Dreamweaver and Flash Builder.  After some unfruitful discussion with Adobe Singapore – they didn’t want anything to do with it.  How stupid is that!?  It would have been an excellent and unique opportunity for them to win the hearts and minds of developers in the region.  Although I did a pretty good job by myself.  I’m not officially an Adobe evangelist.  But people respect my untethered opinions more than they respect Adobe or its evangelists nowadays.

I hear about Adobe employees being laid off.  So let’s hope that the axe has fallen with callous severely on Singapore.  Because Adobe’s Group Marketing team there are about as effective as a chocolate teapot.

Mostly, I’ve been really worried about the ferocity with which Adobe had been pushing Flex for mobile.  Putting all Adobe’s AIR for mobile eggs in the Flex basket was a dreadful mistake.  Flex is tolerable inside its niche.  Bloated enterprise apps.  But if Adobe pushes the notion that Flex 4.6 can export to compete on consumer app stores – then the harder they fight to win that battle, the more they risk losing the war.

The war is the general perception of Adobe AIR on mobile.  And it could make or break Adobe.

I’ve always described the power of Pure ActionScript AIR as Adobe’s best kept secret.  If Adobe take the lean meat of AIR 3, and sandwich it inside layers of fat and bloated Flex… Well, it’s no wonder that the wider developer community is deterred from a technical standpoint.  Flex has already compromised the credibility of AIR on the desktop (  see: http://al3x.net/2011/01/15/user-hostile-platforms.html  In that article, if you scroll down to the third paragraph of “Postscript, January 16 2011″…  “… the developer of JamCloud who claims that the poor performance of many AIR apps is avoidable by using AS3 and not Flex”. ).

This is what I had against Flex.  It was threatening the survival of the entire mobile future of AIR and the Flash Platform.

So I’m pleased that Adobe is turning away from Flex.

Ungrateful maybe, because as a Senior Flex Developer I’d made good money from Flex. But familiarity with Flex lead to contempt, and often frustration, about the limitations of Flex compared to Pure ActionScript.

Sure, Flex made cool “look how easy this is” , “Drag and Drop” demos – but Flex was a real pain to scale up to anything real.

Even though I hated it in the browser and desktop – I can’t see an alternative right now.  I find it hard to imagine HTML5/JavaScript in this space.  I guess I’ll have to wait and see.

I think Flex inhibited the adoption and development of more lightweight, possibly better, AS3 frameworks that were around.  After all, who was going to take notice of anything else, if Adobe was throwing all it’s weight behind Flex.  Now it’s gone, I wonder if developers can fill the void?

After all, the general idea of Flex was ok.  It was just the bloated implementation that was awful.

In the mobile space, we’re ok.  We still have a great framework.  MadComponents.  A lot of developers are using this now for both enterprise and consumer apps.  I’m currently improving JSON support, and adding a SplitView and other enhancements to the extended library.  Watch this space.  Despite the FUD, I’m still enthusiastic and committed to AIR and the MadComponents project.  Even more so now Flex is dying.

October 11, 2011 / Daniel Freeman

Improved Pure ActionScript support in MadComponents

I’ve been wrapped up with other projects lately – so I haven’t had the time to blog about MadComponents.  But in my absence, Michael Martinez has been blogging some interesting tutorials.  And there’s more on the way.

Michael also created the MadComponents logo shown in the corner.

MadComponents is up to version 0.6.2.  The last two minor updates and new examples are for the benefit of developers who prefer to code in a procedural Pure ActionScript style, rather than XML layouts.

Why XML Layouts?

Expressing a MadComponents layout in XML accomplished three things behind the scenes (that you don’t need to think about):-

1. It adapts the layout to the screen size. Different devices have different screen sizes. An XML layout description is relative, not absolute.

2. It scales the layout adjusting to the pixel density of the device. For example, one of my test devices is an HTC desire. It has quite a high pixel density. If it were not for the automatic scaling, the MadComponents UI components would be too tiny to operate.

3. It automatically adapts to screen orientation. When the device is rotated between portrait and landscape – the UI is re-drawn.

These three features save you a lot of trouble. That’s why I based MadComponents on an XML layout description, rather than programmatic UI creation.  There’s no need to worry about bloated-ness either.  Some developers with experience of Adobe Flex and MXML might worry that an XML layout leads to bloated code.  But the problem with Flex isn’t MXML, and there’s nothing inherently inefficient about XML parsing and UI rendering – provided that the UI components are optimised for mobile devices.

But…

While I still advocate the XML approach that I’ve described previously, not all developers like this approach.  Some would prefer having more control to do things their own way, rather than allow the MadComponents framework to take the reins.

So I’ve made some small changes to MadComponents, and added some helper classes to allow developers to get more out of MadComponents without XML.

UIPickerBank

UIPickerBank is a helper class that enables you to create a bank of pickers.

new UIPickerBank(this, 10, 20, 320.0, 434.0, 4);

This will create a picker bank with 4 columns at absolute coordinates (10,20), width 320 pixels, and height 434 pixels.  There is a further optional parameter to specify widths.  For example, “30,20%,30%,50%” specifies 30 pixels, and then the remaining width allocated in the ratio 20%,30%,50%.

There’s an example of using the programmatic picker bank here.

UIListMaker

UIListMaker is a helper class to simplify making a list programmatically.

new UIListMaker(this, 0, 0, 320.0, 434.0);

This will create a list at (0,0), with width 320, and height 434.

There’s an example of creating a programmatic list here, and another example with a pure actionscript custom renderer here.

UIFormMaker and attachPages

UIFormMaker allows you to make pages that you can add to a pages, viewflipper, or navigation container using the attachPages method.

For example:-

var navigation:UINavigation = new UINavigation(this, <null/>, new Attributes(0, 0, WIDTH, HEIGHT));

var page0:UIFormMaker = new UIFormMaker(navigation, WIDTH, PAGE_HEIGHT);

var page1:UIFormMaker = new UIFormMaker(navigation, WIDTH, PAGE_HEIGHT);

navigation.attachPages([page0, page1]);

To add components to a UIFormMaker page, don’t use addChild(), use attach(), attachHorizontal(), or attachVertical() methods of UIFormMaker.  For example:-

page0.attach(uiButton); // Adds the button to the page.

page0.attachVertical(uiButton); // Adds the button, and positions it vertically below the last component.

page0.attachHorizontal(uiButton); //Adds the button, and positions it to the right of the last component.

There’s an example of creating a programmatic navigation based application here.

Help Spread the Word

I’ve contributed these components freely to the Flash Mobile developer community.  Please help spread the word about MadComponents and ExtendedMadness, by blogging and twittering.  It would be great if you could contribute more examples and tutorials, or even just talk about these libraries and what they can do.

Please click on the star on the Project Home page (log-in to see it under Project Information), to show your appreciation of MadComponents.

September 6, 2011 / Daniel Freeman

MadComponents now open source with in-depth documentation

MadComponents0_6_0.swc is available now.

MadComponents is a free open-source library to make user interfaces for Flash/AIR on Mobile.  (iPhone, Android, etc.).  MadComponents projects can be authored using either Flash, Flex (Flash Builder), or command line tools (amxmlc, adt).

The main update to this version is a new list component called <longList>.  The older list components are rendered on creation.  So a long list would be created when the application starts up – which could impact on app start-up performance.  But the <longList> component is rendered lazily, when list rows come into view.  There is also a recycle option:

<longList recycle=”true”/>

Enabling recycle re-uses list rows that have rolled off the screen, rather than instantiating new list rows.  So it is optimised to minimise run time memory.

(Note that <longList> only employs this lazy row rendering or recycling for custom row layouts).

MadComponents is now open-source.  You can access the source from here.  While MadComponents has always been free to use, I wanted to wait until the library was mature and stable before releasing the source.

I’ve also published the asdoc documentation at http://e2easy.byethost9.com/madcomponents .

In related news, Michael Martinez is writing a series of blog articles on MadComponents here.

A MadComponents Logo

Can anyone anyone make a MadComponents logo?  (for free obviously).  It would be nice to have a logo.

Help Spread the Word

I’ve contributed MadComponents freely to the Flash Mobile developer community.  Please help spread the word about MadComponents and ExtendedMadness, by blogging and twittering.  It would be great if you could contribute more examples and tutorials, or even just talk about these libraries and what they can do.

August 16, 2011 / Daniel Freeman

Flex wrappers for MadComponents

I’ve had feedback from a few developers wanting a way to combine MadComponents with Flash Builder 4.5 for mobile.  I intended MadComponents as a lighweight alternative to using the Flex framework.  So while I don’t really like the idea of mixing them – it’s certainly possible to incorporate MadComponents within an MXML layout.  All it takes is a few custom component wrappers.

Note: I’ve now put the code for these wrappers into the SVN code repository.

For example, here’s a UIForm wrapper extending SpriteVisualElement:-

package custom {

	import com.danielfreeman.madcomponents.Attributes;
	import com.danielfreeman.madcomponents.UIForm;

	import flash.display.Sprite;
	import spark.core.SpriteVisualElement;

	public class FlexUIForm extends SpriteVisualElement
	{
		protected var _component:Sprite;
		protected var _gap:Number = 0;
		protected var _xml:XML;
		protected var _attributes:Attributes;

		public function FlexUIForm() {
		}

		override public function setLayoutBoundsSize(width:Number, height:Number, postLayoutTransform:Boolean=true):void {
			if ( isNaN( width ) )
				width = getPreferredBoundsWidth( postLayoutTransform );

			if ( isNaN( height ) )
				height = getPreferredBoundsHeight( postLayoutTransform );

			if (!_component) {
				createComponent(width - 2*_gap, height - 2*_gap);
			}
			else {
				resizeComponent(width - 2*_gap, height - 2*_gap);
			}

			super.setLayoutBoundsSize(width, height, postLayoutTransform);
		}

		protected function createComponent(width:Number, height:Number):void {
			_attributes = new Attributes(0, 0, width, height);
			_attributes.parse(_xml);
			_component = new UIForm(this, _xml, _attributes);
			_component.x = _gap;
			_component.y = _gap;
		}

		protected function resizeComponent(width:Number, height:Number):void {
			_attributes.width = width;
			_attributes.height = height;
			UIForm(_component).layout(_attributes);
		}

		public function get component():Sprite {
			return _component;
		}

		public function set xml(value:XML):void {
			_xml = value;
		}

		override public function get height():Number {
			return _component ? _component.height + _gap : super.height;
		}

		override public function get width():Number {
			return _component ? _component.width + _gap : super.width;
		}

	}
}

The code above is pretty standard, except overriding width, and height.  This compensates for components that incorporate masking.

Notice, we can specify a MadComponents layout, and pass it to the xml property.

We can use our FlexUIForm component as a base class for specific components.  I anticipate that Flex developers are going to really like my picker component, so let’s specify a wrapper for that:-

package custom {

	import com.danielfreeman.madcomponents.Attributes;
	import com.danielfreeman.madcomponents.UIForm;

	public class FlexUIPicker extends FlexUIForm {

		protected var _columns:int = 1;
		protected var _data:Array = null;
		protected var _xmlData:XML = null;
		protected var _widths:String = "";
		protected var _pickerHeight:String = "";

		public function FlexUIPicker() {
			_gap = 10;
		}

		public function set columns(value:int):void {
			_columns = value;
		}

		public function set widths(value:String):void {
			_widths = value;
		}

		public function set pickerHeight(value:String):void {
			_pickerHeight = value;
		}

		public function set data(value:Array):void {
			if (_component) {
				var pickerIndex:int = 0;
				for each (var columnData :Array in value) {
					UIForm(_component).pages[pickerIndex++] = columnData;
				}
			}
			else {
				_data = value;
				_xmlData = null;
			}
		}

		public function set xmlData(value:XML):void {
			if (_component) {
				var pickerIndex:int = 0;
				for each (var columnData :XMLList in value) {
					UIForm(_component).pages[pickerIndex++] = columnData[0];
				}
			}
			else {
				_xmlData = value;
				_data = null;
			}
		}

		override protected function createComponent(width:Number, height:Number):void {
			var xml:String = '<columns gapH="0" width="'+width.toString()+'"';
			if (_pickerHeight!="") {
				xml += ' pickerHeight="' + _pickerHeight.toString() + '"';
			}
			if (_widths!="") {
				xml += ' widths="' + _widths + '"';
			}
			xml += '>';
			var index:int = 0;
			for(var i:int = 0; i<_columns; i++) {
				xml += '<picker>' + theData(index++) + '</picker>';
			}
			_xml = XML(xml + '</columns>');
			super.createComponent(width, height);
		}

		protected function theData(value:int):String {
			if (_data) {
				var result:String = '<data>';
				for each (var item:String in _data[value]) {
					result+='<item label="'+item+'"/>';
				}
				return result+'</data>';
			}
			else if (_xmlData) {
				var group:String = _xmlData.group[value].toString();
				return "<data"+group.substring(group.indexOf(">"),group.lastIndexOf("<"))+"</data>";
			}
			else {
				return "";
			}
		}

	}
}

Notice within createComponent, we build up a string for the picker bank xml, that incorporates the xml data for each picker.  We can specify this data either as a two dimensional array (assigned to data), or as a grouped data XML (assigned to xmlData).

While I’ve allowed the user to specify columns, pickerHeight, and widths within the MXML component, I haven’t gone as far as allowing every MadComponent property to be defined.  I wanted to demonstrate the principle of how to make a MadComponents wrapper, so I leave it as an exercise for the reader to expand and refine what I’ve shown here.  So, I’ve omitted the ability to specify colour, colours, index (for each picker) and the font for the labels in each picker row.

It would be great if someone wants to expand on what I’ve done and write a complete set of Flex wrappers for MadComponents, and share them with the community.  I don’t have the time or inclination to pursue this myself.  It would be great to see spin-offs from MadComponents, in the same way that minimal comps has spawned spin-off projects.  (MadComponents will be open-source soon – when I feel it is mature, stable, developed, and robust enough to release – but for now the .swc library is free to use, or extend.).

The final two wrappers are for UISlider and UISwitch.

package custom {

	import com.danielfreeman.madcomponents.UISlider;

	public class FlexUISlider extends FlexUIForm {

		public function FlexUISlider() {
		}

		override protected function createComponent(width:Number, height:Number):void {
			_component = new UISlider(this, 0, 0, new <uint>[]);
			UISlider(_component).fixwidth = width;
		}

		override protected function resizeComponent(width:Number, height:Number):void {
			UISlider(_component).fixwidth = width;
		}
	}
}

 

package custom {

	import com.danielfreeman.madcomponents.UISwitch;

	public class FlexUISwitch extends FlexUIForm {

		public function FlexUISwitch() {
		}

		override protected function createComponent(width:Number, height:Number):void {
			_component = new UISwitch(this, 0, 0);
		}

		override protected function resizeComponent(width:Number, height:Number):void {
		}
	}
}

Finally, the root MXML project that demonstrates all four of these wrappers in action:-

<?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"
			   xmlns:mad="custom.*">

	<fx:Script>
		<![CDATA[
			protected static const LAYOUT:XML =

		<horizontal>
			<slider id="slider2" value="0.2" width="130" background="#CCCC00,#999933,#AAAA99"/>
			<button id="slideDown" colour="#CC9933" alt="true">button</button>
		</horizontal>;

			protected static const GROUPED_DATA:XML =

		<data>
			<group>
				<Black/>
				<Red/>
				<Orange/>
				<Yellow/>
				<White/>
				<Green/>
				<Blue/>
				<Indigo/>
			</group>
			<group>
				<January/>
				<February/>
				<March/>
				<April/>
				<May/>
				<June/>
			</group>
			<group>
				<item label="1"/>
				<item label="2"/>
				<item label="3"/>
				<item label="4"/>
				<item label="5"/>
			</group>
		</data>;

		]]>
	</fx:Script>

	<s:VGroup width="300" height="400">
		<mad:FlexUISlider percentWidth="100"/>
		<mad:FlexUISwitch/>
		<mad:FlexUIForm xml="{LAYOUT}" percentWidth="100"/>
<mad:FlexUIPicker columns="3" xmlData="{GROUPED_DATA}" widths="50%,50%,40" percentWidth="100" height="200" />
	</s:VGroup>

</s:Application>

Help Spread the Word

I’ve contributed these components freely to the Flash Mobile developer community.  Please help spread the word about MadComponents and ExtendedMadness, by blogging and twittering.  It would be great if you could contribute more examples and tutorials, or even just talk about these libraries and what they can do.

Please click on the star on the Project Home page (log-in to see it under Project Information), to show your appreciation of MadComponents.

July 28, 2011 / Daniel Freeman

ExtendedMadness. More components and charts for mobile developers.

I wanted to keep MadComponents lightweight.  So I packed the most essential UI components and data capabilities into a small library.  But  I had more UI components that I wanted to contribute to Adobe mobile developers.  So I created ExtendedMadness.  The ExtendedMadness .swc does everything that the MadComponents .swc does, but also includes more components and charts.  The treeNavigation, and DataGrid, which were deprecated in MadComponents, have also made their way into ExtendedMadness.

Just like MadComponents, you can use ExtendedMadness within Flash or Flex (Flash Builder).  You can utilise it in Mobile AIR applications, or desktop AIR applications, or browser web services.  You use the same XML layout language as MadComponents, and you can freely mix MadComponents, and ExtendedMadness tags.

(If you don’t know about MadComponents yet – I recommend that you read other posts on this blog, and gain some insight into the approach, before reading any further).

Above you can see combo-boxes (drop-down menu), Cut-copy-paste control, segmented controls, checkboxes, and radio buttons.  Below are four examples of charts included in ExtendedMadness.

Set up an ExtendedMadness project

If you have a project utilising MadComponents (and you can read detailed tutorials on this blog about how to do that), then you can change it to an ExtendedMadness project as follows:-

1. Replace the MadComponents.swc library with an ExtendedMadness.swc library.

2. Ensure you have these imports at the top of the program:-

import com.danielfreeman.extendedMadness.*;
import com.danielfreeman.madcomponents.*;

3. Put another line of code above the UI.layout() statement:-

UIe.activate(this); // Gives us access to extended components
UI.create(this, LAYOUT);

(Note UIe - the “e” is not a typing error).

4. Now you can use extended tags in the XML layout.

Now let’s go through the components shown above, and how to describe them in XML.

Combo-box Menu.

<menu value=”choose…”>
      {DATA}
</menu>

Where DATA is defined in the usual way:-

<data>
      <dog/>
      <cat/>
      <goldfish/>
</data>

You can define a width, and alternative appearance for a menu.  You can also define a font:-

<menu value=”choose…”  width=”100″  alt=”true”>
      <font size=”20″/>
      {DATA}
</menu>

Usually, alt=”true” means that the component style will be smaller, and more appropriate for desktop or browser use, rather than mobile use.

Listen for a menu selection like this:-

var menu:UIMenu = UIMenu(UI.findViewById(“menu”));
menu.addEventListener(UIMenu.SELECTED, menuSelected);
 
protected function menuSelected(event:MyEvent):void {   // import asfiles.MyEvent
      trace(“menu: “+event.parameters[0]+” “+event.parameters[1]);
}

Segmented Control

<segmentedControl>
      {DATA}
</segmentedControl>

You can also specify width, alignH, alt=”true”, or background colours to customise appearance.   Listen for button clicks like this:-

protected var _segmentedControl:UISegmentedControl;
 
_segmentedControl = UISegmentedControl(UI.findViewById(“segmentedControl”));
_segmentedControl.addEventListener(Event.CHANGE, segmentedControlChanged);
 
protected function segmentedControlChanged(event:Event):void {
       trace(“segmented control: “+_segmentedControl.index);
}

checkBox

<checkBox/>
<checkBox alt=”true”/>
 
protected var _checkBox:UICheckBox;


_checkBox = UICheckBox(UI.findViewById(“checkBox”));
_checkBox.addEventListener(Event.CHANGE, checkBoxChanged);
 
protected function checkBoxChanged(event:Event):void {
      trace(“check box:”+_checkBox.state);
}

radioButton

<columns widths=”50,50,50″>
      <radioButton/>
      <radioButton/>
      <radioButton/>
</columns>
 
_radioButtons = UIPanel(UI.findViewById(“radioButtons”));
_radioButtons.addEventListener(UIRadioButton.TOGGLE, radioButtonsChanged);
protected function radioButtonsChanged(event:MyEvent):void {
      trace(“radio button: “+UIRadioButton(event.parameters[0]).name);
}

Charts

ExtendedMadness includes five kinds of chart.  pieChart, barChart, lineChart, scatterChart, and horizontalChart (horizontal barChart).  Some charts are automatically calibrated, according to how much space the graph takes in the layout.  When the user clicks on a chart, a tool-tip appears.

By default, pieChart, barChart, and horizontalChart are rendered in 3D.  Change them to 2D as follows:-

<pieChart render=”2d”/>

barChart and horizontalChart can be stacked as follows:-

<barChart stack=”true”/>

Assign data to the chart within the XML layout, or in ActionScript.  For example,

protected static const MATRIX:XML = <data>
           <row>1,2,3,4</row>
           <row>3,8,4,1</row>
           <row>4,1,5,12</row>
          <row>7,14,0,4</row>
          <row>6,8,3,1</row>
          <row>5,7,9,2</row>
  </data>;
 
<barChart>{MATRIX}</barChart>

or in ActionScript:-

var barChart:UIBarChart = UIBarChart(UI.findViewById(“barChart”));
barChart.data = [[4,3,2,5,6],[4,8,15,16,23]];
// or
barChart.xmlData = <data><row>4,3,2,5,6</row><row>4,8,15,16,23</row></data>;

The charts interpret the data row-by-row, unless you specify column-by-column like this:-

<barChart id=”barChart” order=”column”/>
 
 

Customise Chart Colours

There are a few ways to change the colours of a chart.  You can use a different colour palette.  There are four preset palettes.  ”rainbow”, “subtle”, “greyscale0″ and “greyscale1″.  Some palettes look best with order=”row” (default), and some look best with order=”column”.  So it’s worth experimenting.  For example:-

<barChart stack=”true” palette=”subtle” order=”columns”>{MATRIX}</barChart>

A palette is a cyclic-list of preset colours.  To start at a specific place in that list, use paletteStart, like this:-

<horizontalChart id=”hChart”  paletteStart=”5″/>

Another way to specify chart colours is to use a custom colour list, like this:-

protected static const COLOURS:XML = <colours>#99FF99,#CC9999,#9999CC,#CCCC66,#CC9966</colours>;
 
<pieChart>{COLOURS}{DATA}</pieChart>
 
 

SVG Renderer

I’ve been completely self-indulgent, and included an SVG renderer in the library.  You can specify vector images between the <svg> tags.  I made this SVG parser myself, and it’s pretty good, with a few quirks occasionally, where the result differs from what you get in a browser.  Of course, on a mobile screen, it’s better to use .jpg bitmap images rather than to render complex vector images.

I got this particular SVG sample from  http://www.openclipart.org.

 

 

Get ExtendedMadness

Flash users can download the ExtendedMadness.swc from http://code.google.com/p/mad-components/downloads/list .

Flex (Flash Builder) users can check-out the latest .swc and MadComponents demos from the Subversion repository at: http://code.google.com/p/mad-components/source/checkout .

Example code using ExtendedMadness can be found here.

Help Spread the Word

I’ve contributed these components freely to the Flash Mobile developer community.  Please help spread the word about MadComponents and ExtendedMadness, by blogging and twittering.  It would be great if you could contribute more examples and tutorials, or even just talk about these libraries and what they can do.

Follow

Get every new post delivered to your Inbox.

Join 32 other followers