Skip to content
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.

Advertisements

8 Comments

Leave a Comment
  1. Valentine / Aug 25 2011 12:27 pm

    Hi! How I can update Slider value (with slider thumb position update) by click on the track of slider?
    thanks for sharing!

    • Daniel Freeman / Aug 25 2011 1:38 pm

      When you mentioned clicking on the slider track – I had to quickly go into XCode and confirm how Apple’s slider works, and that MadComponents behaved the same way. Yup, it does. Touching on the track, does not move the slider to that position. Only dragging the handle moves the slider.

      You can position the slider in code:-

      protected var _uiSlider:UISlider;

      _uiSlider = UISlider(UI.findViewById(“mySliderId”));
      _uiSlider.value = n; //Where n is a Number between 0 and 1.

      If you wanted to click on the track to move the slider, you could set up a MouseEvent.MOUSE_UP listener on it, and do this in the handler…

      _uiSlider.value = _uiSlider.mouseX/_uiSlider.width;

      . . . . . .

      Sorry, this is the Flex wrapper we’re talking about here, isn’t it.

      So let’s say you’ve got:-

      <mad:FlexUISlider id=”slider” percentWidth=”100″/>

      Provided the component has loaded, you can say:-

      UISlider(slider.component).value = n; //Where n is a Number between 0 and 1.

      So for the Flex wrappers, you access the actual madComponent via this component property of the wrapper.

      • Valentine / Aug 25 2011 3:07 pm

        Daniel, thank you for detailed answer!

  2. Danny Froberg / Sep 22 2011 9:22 am

    SIlly question maybee but how in heavens name do I get the value of a selected object in the FlexUIPicker?

    Invokation is per your example;
    [mad:FlexUIPicker id=”reasonPicker” columns=”1″ xmlData=”{MH_DATA}” widths=”100%” percentWidth=”100″ height=”100″ click=”flexuipicker1_clickHandler(event)”/]

    • Daniel Freeman / Sep 24 2011 4:37 am

      As long as the FlexUIPicker has loaded, you can set up a listener on the UIPicker.

      UIForm(reasonPicker.component).addEventListener(Event.EVENT, clickHandler);

      I’ve updated the FlexUIPicker component (on the Google code site) so each picker has an id, so you can say:-

      var picker0:UIPicker = UIPicker(UIForm(reasonPicker.component).findViewById(“column0”));

      etc.. etc..

      so picker0.index, etc, will give you the selected index.

  3. pacohernandezg / Feb 1 2012 6:32 pm

    Hello Daniel.

    First of all. I have discovered your components today, and I love them.

    I have been using Flex for two or three years, but I began to develop my first mobile application last week, so, I discovered that Flex is really slow for mobile development. So, I decided to use AS3 only, then I discovered MadComponents. I have been testing the components in my HTC Desire and they are terrific. 😉

    I have been reading this post http://www.ryancampbell.com/2009/08/26/using-mxml-without-flex-example-and-source/ and I wondered if you think that it could be interesting to use MadComponents in MXML without Flex.

    I am trying to figure out how to use actual XMLs with a Robotlegs mediator, but I don’t see it. Any help would be very appreciated.

    Thanks a lot for this component library. I think these components are very important to AIR continuity in mobile development.

    • Daniel Freeman / Feb 2 2012 7:23 am

      I was hoping someone would want to look into this. While MadComponents already has an XML language, developers who are more comfortable with MXML might benefit from the minimal approach.

      As far as I can tell, it will involve modifying each component (or wrapper) so each is subclassed from Keith Peter’s Component.as. But speculating about this was as far as I got.

      I think of the XML View and the AS3 view controller as already separated. Maybe Robotlegs might be employed between the Controllers and Model. That’s what I think, but I’m not sure.

Trackbacks

  1. Cool Stuff with the Flash Platform - 8/19/2011 | Remote Synthesis

To discuss MadComponents/MC3D, join the Facebook group!

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: