Skip to content
May 27, 2011 / Daniel Freeman

MadComponents sans XML

MadComponents is a free 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).

Usually, the layout is defined using XML.  This approach will be familiar to developers who’ve used HTML, Adobe MXML, Java Swing, or native Android development.  The advantage of an XML layout description is that the renderer can adapt for different screen sizes and resolutions.

By the way, for a bit more control over the positioning of components described by an XML layout, you can always use an <image> as a spacer/padding.

eg:  <vertical><switch/><image>45,25</image><switch/></vertical>

…where 45 is the width, and 25 the height.

But for precise absolute positioning, it is possible to utilise MadComponents in a good ol’ fashioned Pure ActionScript way, in ActionScript 3.

For example…

package
{

	import com.danielfreeman.madcomponents.*;

	import flash.display.Sprite;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;
	import flash.text.TextFormat;

	public class MadComponentsPure extends Sprite {

		public function MadComponentsPure() {

			stage.align = StageAlign.TOP_LEFT;
			stage.scaleMode = StageScaleMode.NO_SCALE;

			var label:UILabel = new UILabel(this, 20, 10, "Hello World", new TextFormat("Times",24,0xCCCCCC,true));
			var button:UIButton = new UIButton(this, 20, 50, "button", 0xCCFFCC, new <uint>[]);
			button.fixwidth = 80.0;
			var slider:UISlider = new UISlider(this, 20, 100, new <uint>[]);
			slider.fixwidth = 160.0;
			slider.value = 0.3;
			var input:UIInput = new UIInput(this, 20, 140, "input", new <uint>[0x9999AA,0xEEEEFF], true);

			var picker0:UIPicker = new UIPicker(this, <picker/>, new Attributes(20,200,120,200), false, false);
			var picker1:UIPicker = new UIPicker(this, <picker/>, new Attributes(140,200,40,200), false, false);
			var picker2:UIPicker = new UIPicker(this, <picker><data><year label="2010"/><year label="2011"/><year label="2012"/></data></picker>, new Attributes(180,200,80,200), false, false);

			picker0.xmlData = <data>
								<January/>
								<February/>
								<March/>
								<April/>
								<May/>
								<June/>
								<July/>
								<August/>
								<September/>
								<October/>
								<November/>
								<December/>
							</data>;

			var data:Array = [];
			for (var i:int = 1; i<=31; i++) {
				data.push({label:i.toString()});
			}
			picker1.data = data;</pre>
var uiSwitch:UISwitch = new UISwitch(this ,20, 380);
		}
	}
}

Notes on the above example:-

1. The vector parameter ( new <uint>[] ) can contain the colour values usually expressed in the XML background attribute.  (See layout documentation http://code.google.com/p/mad-components/downloads/list )

2. The picker has an attributes parameter which defines a rectangle (x, y, width, and height).

3. Note 3 ways to populate a list or picker.  XML data description, assign array to list.data, or assign XML to list.xmlData.

4. Also note two ways to describe list values in XML:   <item label=”one”/><item label=”two”/><item label=”three”/>  or the shorthand way: <one/><two/><three/>

Here are some further examples of defining pickers and lists in Pure ActionScript:-

package
{
	import flash.display.Sprite;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;
	import com.danielfreeman.madcomponents.*;

	public class MadComponentsPurePicker extends Sprite {

		protected static const DATA:XML = <data>
											<Apple/>
											<Orange/>
											<Banana/>
											<Pineapple/>
											<Lemon/>
											<Mango/>
											<Plum/>
											<Cherry/>
											<Lime/>
											<Peach/>
											<Pomegranate/>
											<Grapefruit/>
											<Strawberry/>
											<Melon/>
										</data>;

		public function MadComponentsPurePicker() {
			stage.align = StageAlign.TOP_LEFT;
			stage.scaleMode = StageScaleMode.NO_SCALE;

			var columns:UIForm = new UIForm(this, <columns gapH="0"><picker>{DATA}</picker><picker>{DATA}</picker></columns>,new Attributes(0,0,280,200));
			columns.x = 20;
			columns.y = 40;
		}
	}
}

package
{

	import com.danielfreeman.madcomponents.*;

	import flash.display.Sprite;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;
	import flash.text.TextFormat;

	public class MadComponentsPureList extends Sprite {

		public function MadComponentsPureList() {

			stage.align = StageAlign.TOP_LEFT;
			stage.scaleMode = StageScaleMode.NO_SCALE;

			var list:UIList = new UIList(this, <list/>, new Attributes(0,0,320,480));

			list.xmlData = <data>
								<January/>
								<February/>
								<March/>
								<April/>
								<May/>
								<June/>
								<July/>
								<August/>
								<September/>
								<October/>
								<November/>
								<December/>
							</data>;

		}
	}
}

Get the latest version, and documentation for MadComponents from:-

http://code.google.com/p/mad-components/downloads/list

Flex (Flash Builder) users can check out examples from the subversion repository:-

http://code.google.com/p/mad-components/source/checkout

Flash users can build MadComponents mobile applications using Flash.  Just follow the instructions at:-

https://madskool.wordpress.com/2011/04/24/getting-started-with-madcomponents-in-flash/

UPDATE:-

I noticed a Burrito flavoured post on Adobe feeds, concerning IOS style buttons in Flex 4.5, prompting me to write this update, about how to achieve a similar outcome in MadComponents 0.3.9+.  For example:-

<navigation id=”nav” rightButton=”done”/>

<navigation id=”nav” rightArrow=”next”/>

You can listen for clicks like this:-

var nav:UINavigation = UINavigation(UI.findViewById(“nav”));

var bar:UINavigationBar = nav.navigationBar;

bar.rightButton.addEventListener(UIButton.CLICK,rButtonClick);

//or

bar.rightArrow.addEventListener(MouseEvent.MOUSE_UP,rArrowClick);

103 Comments

Leave a Comment
  1. Adam Coburn / Jun 1 2011 3:45 am

    How would I push data to a DividedList to different groups?

    • Daniel Freeman / Jun 1 2011 6:36 am

      Three ways.

      1. The first is to include an XML literal in the layout:-

      [dividedList id=”dividedList”]
      [data]
      [group label=”zero”]
      [Black/]
      [Blue/]
      [/group]
      [group label=”one”]
      [Red/]
      [Orange/]
      [Yellow/]
      [White/]
      [/group]
      [/data]
      [/dividedList]

      (It seems that wordpress doesn’t like less than and greater than characters in comments. So intead of square bracjkets above, it should look like XML of course.)

      2. Assign to the data property.

      var divList:UIDividedList = UIDividedList(UI.findViewById(“dividedList”));
      divList.data = [“zero”,[{label:”black”},{label:”blue”}],”one”,[{label:”Red”},{label:”Orange”},{label:”Yellow”}];

      3. Assign to the xmlData property.

      divList.xmlData = [data]
      [group label=”zero”]
      [Black/]
      [Blue/]
      [/group]
      [group label=”one”]
      [Red/]
      [Orange/]
      [Yellow/]
      [White/]
      [/group]
      [/data];

      But I’ve just realised that there is a flaw with rewriting to the divided list. In version 0.4 it seems that you can’t refresh the list with new data. I need to fix this – probably get it done this evening (UK time). Look out for version 0.4.1 later.

  2. Adam Coburn / Jun 1 2011 11:57 am

    Thanks man I will try this. I was going the right direction. Was missing a small part. Can I follow the format of a normal list inside the group?

    32

  3. Adam Coburn / Jun 1 2011 11:59 am

    Sorry last post got messed up

    [dividedList id=”divlist”]
    [search id=”search”/]
    [group label=”Processor”]
    [horizontal]
    [image id=”image”]32[/image]
    [horizontal alignH=”fill”]

    [vertical]
    [label id=”label” width=”250″/]
    [label id=”label2″/]
    [/vertical]
    [label alignH=”right” width=”50″ id=”price”/]

    [/horizontal]
    [/horizontal]
    [/group]
    [group label=”Storage”]

    [/group]
    [group label=”Memory”]

    [/group]

  4. Adam Coburn / Jun 1 2011 5:06 pm

    Adam Coburn :
    Sorry last post got messed up
    [dividedList id=”divlist”]
    [search id=”search”/]
    [group label=”Processor”]
    [horizontal]
    [image id=”image”]32[/image]
    [horizontal alignH=”fill”]
    [vertical]
    [label id=”label” width=”250″/]
    [label id=”label2″/]
    [/vertical]
    [label alignH=”right” width=”50″ id=”price”/]
    [/horizontal]
    [/horizontal]
    [/group]
    [group label=”Storage”]
    [/group]
    [group label=”Memory”]
    [/group]

    Should this work?

    var data0:Array = [];
    for (var i=0; i<products.length(); i++) {

    data0.push({label:'’+String(products[i].producttitle)+”, image:”AndroidStore_”+products[i].producticon, label2:’here is some small text’,price:”+String(products[i].productprice)+”});
    }
    var data1:Array = [“Processor”,data0,”Storage”,data0,”Memory”,data0]
    var uiList1:UIDividedList = UIDividedList(UI.findViewById(“divlist”));
    var pGroup:UIList = UIList(uiList1.findViewById(“Processor”));
    pGroup.data = data1;

    • Daniel Freeman / Jun 1 2011 5:55 pm

      While you can define a custom item renderer for a grouped or divided list (the same as you can for a list/ticklist/tickOneList) – you can’t define different item renderers for each group.

      So the [group] tags in your XML won’t be recognised. (unless inside [data]). If you take them out, and put a [/dividedList] at the end – it should be right.

      In your code, the last line should be uiList1.data = data1. And you can omit the line before it.

      I’m working on a 0.4.1 release – that I’ll try and upload tonight.

  5. Adam Coburn / Jun 1 2011 7:50 pm

    Thanks man. Super awesome work by the way. You have saved me tons of time and with a really slick interface.

    • Daniel Freeman / Jun 1 2011 8:52 pm

      0.4.1 is on the google code site now. Also take a browse around the source of the demos. MadComponentsDividedList.as is similar to what you’re doing.

  6. Manx / Jun 2 2011 2:14 pm

    I am trying to use your MadComponents but I guess I just don’t get it. When I open your sample it works fine. But, when I copy your code for just the MadComponentsPureList I get this error: Scene 1, Layer ‘Layer 1’, Frame 1, Line 1 1137: Incorrect number of arguments. Expected no more than 0.

    Can you give me an example FLA and AS for just the list and navigation?

    Thanks,

    • Daniel Freeman / Jun 2 2011 2:35 pm

      To get these running with Flash, you just need to modify the MadComponentsPureList declaration, and add two lines:-

      public function MadComponentsPureList(screen:Sprite = null) {
      if (screen)
      screen.addChild(this);

      I’ve just made these changes to the Google code examples.

      • Manx / Jun 2 2011 4:51 pm

        Thanks for the help, that works fine. Now, If I change the data to have multiple words with spaces I get this error:

        … MadComponentsPureList.as, Line 23 1104: invalid xml name

        Let’s say I change “January” to “January 15” then I get the above error. What I’m wanting to do is to have a list of words such as “This is list item #1”.

        Thanks,

    • Daniel Freeman / Jun 2 2011 5:14 pm

      @Manx

      (Note I don’t seem to be able to write less-than and greater than characters in comments, so I’ll write [ and ] )

      [data]
      [january/]
      [february/]
      [/data]

      is a short way of writing:-

      [data]
      [item label=”january”/]
      [item label=”february”/]
      [/data]

      so you can write:-

      [data]
      [item label=”january 15″/]
      [item label=”This is list item #1″/]
      [/data]

  7. Adam Coburn / Jun 3 2011 12:06 am

    Sorry man, one other question. I like to keep my assets in a SWC… when I refer to them by class names they are BitmapData. I have to pass a DisplayObject class to the images in your xml. My attempts to convert the data to Bitmaps before passing them to the xml have failed, so I have had to stick with embeds like in your examples. Is there a way to pass bitmapData? That would be sweet.

    • Daniel Freeman / Jun 3 2011 9:30 am

      No limit on questions. Ask away. I want this library to be used and useful to people.

      I’ve just uploaded version 0.4.2 which solves your problem. You can use Flash library assets with images now.

  8. Adam Coburn / Jun 3 2011 3:07 pm

    You are so awesome man. Thank you so much! I just tested and it worked great. Now say my BitmapData is dynamic and does not have a specific class name… will it still work?

    • Daniel Freeman / Jun 3 2011 5:01 pm

      You’d have to do something different for a dynamic BitmapData. In ActionScript 3:-

      var myImage:UIImage = UIImage(UI.findViewById(“myImage”));
      if (myImage.numChildren>0) myImage.removeChildAt(0);
      myImage.addChild(new Bitmap(dynamicBitmap));

      (At least I assume this would work)

      • Adam Coburn / Jun 3 2011 11:59 pm

        how would that work in a list row that is being populated by pushing to an array?

      • Daniel Freeman / Jun 4 2011 11:22 am

        You can’t yet. I’ll be looking into fixing other things tonight. And releasing an update. So I’ll see what I can do.

        But if your reason for using a dynamic BitMapdata is to resize it – UIImage scales things automatically to fit.

  9. Manx / Jun 3 2011 3:13 pm

    How do you change the color of the navigation arrows? For example the rightArrow and leftArrow.

    • Daniel Freeman / Jun 3 2011 5:12 pm

      var treeNavigation:UITreeNavigation = UITreeNavigation(UI.findViewById(“myNavigation”));
      treeNavigation.navigationBar.backButton.colour = 0xCCCCCC;
      treeNavigation.navigationBar.rightArrow.colour = 0xCCCCCC;

      • Manx / Jun 10 2011 8:37 pm

        If changing the color of the backButton is:

        treeNavigation.navigationBar.backButton.colour = 0xCCCCCC;

        then I would guess that:

        _navigation.navigationBar.colour = 0xCCCCCC;

        but it doesn’t work… so how do you change the color of the navigation bar?

        Also, is it possible to change the colour of the list click colour? Meaning when you click on an item in a list it now has a purple/blue color. How can I change that colour?

      • Daniel Freeman / Jun 10 2011 9:26 pm

        Define the colour of the navigation bar in the XML:-

        [navigation colour=”#333333″] {LIST} {DETAIL} [/navigation];

        At the moment, you can’t change the highlight colour. But I’ll put it on the list for stuff to do in version 0.4.6.

        You can change the scrollbar colour though. For example:-

        [list scrollBarColour=”#6666CC”/]

  10. Manx / Jun 3 2011 5:59 pm

    I’m beginning to get my head around this and I thank you for it.

    Would it be too much trouble to mock up a treeNavigation sans XML? I would like to look at something that has a couple of lists and a detail page. Something like this:

    List One –> List Two –> Detail Page

    I would also like to see how to layout a “detail page” and the detail page would need to scroll.

    Thanks,

    • Daniel Freeman / Jun 3 2011 8:28 pm

      I’ve put a demo, MadComponentsTree2.as on the Google code site. Oh! – in DETAIL, replace “vertical” with “scrollVertical”, and it would scroll.

      Not easy to do without XML, as the UITreeNavigation object sets up the detail page written in XML. The code turns out more complicated than the XML way.

  11. Manx / Jun 3 2011 8:19 pm

    Kind of along Adam’s work… how would I make this work when pulling the info from a local sqlite database?

    function populateList(event:SQLEvent):void {
    //creates a result variable that holds all our info
    var result:SQLResult=event.target.getResult();
    //we check if results is not empty
    if (result!=null&&result.data!=null) {
    //add list items from datbase
    for (var i:Number = 0; i < result.data.length; i++) {
    list.data = ({ ID:result.data[i].id, Name:result.data[i].somename, Phone:result.data[i].phone});

    }
    }
    }

    I get this error: 1118: Implicit coercion of a value with static type Object to a possibly unrelated type Array.

    • Daniel Freeman / Jun 3 2011 8:31 pm

      list.data = [{ ID:result.data[i].id, Name:result.data[i].somename, Phone:result.data[i].phone}];

      Note square brackets above. Not rounded parenthesis.

      Oh, you need to accumulate the list first, then write it to the list.

      var data:Array = [];
      for (var i:Number = 0; i < result.data.length; i++) {
      data.push({ ID:result.data[i].id, Name:result.data[i].somename, Phone:result.data[i].phone});
      }
      list.data = data;

      • Manx / Jun 3 2011 10:31 pm

        OK, I tried what I think you were showing:

        function populateList(event:SQLEvent):void {
        //creates a result variable that holds all our info
        var result:SQLResult=event.target.getResult();
        //we check if results is not empty
        if (result!=null&&result.data!=null) {
        //add list items from database
        var data:Array = [];
        for (var i:Number = 0; i < result.data.length; i++) {
        data.push({ ID:result.data[i].id, Name:result.data[i].watername});
        }
        list.data = data;
        }
        }

        But, I get this error:

        Error #2007: Parameter text must be non-null.
        at flash.text::TextField/set text()
        at com.danielfreeman.madcomponents::UIList/simpleRenderers()[/Users/danielfreeman/Documents/Adobe Flash Builder 4/MadComponentsLib/src/com/danielfreeman/madcomponents/UIList.as:195]
        at com.danielfreeman.madcomponents::UIList/set data()[/Users/danielfreeman/Documents/Adobe Flash Builder 4/MadComponentsLib/src/com/danielfreeman/madcomponents/UIList.as:166]
        at Function/MadComponentsTree/$construct/populateList()[/Users/abc/xyz/MadComponentsTree.as:74]
        [UnloadSWF] example.swf
        Test Movie terminated.

        Any ideas?

  12. Daniel Freeman / Jun 3 2011 10:40 pm

    @Manx,

    You have two fields. ID and watername. So you’ll want create a custom item renderer:-

    [list] [horizontal] [label id=”ID” width=”100″ /] [label id=”watername”/] [/horizontal] [/list]

    As things are now, it’s failing in simpleRenderers() because it can’t find {label:”something”} in the object.

    • Manx / Jun 3 2011 10:49 pm

      I don’t really need “ID” just watername. Can I just delete “ID:result.data[i].id, ” and it should work? Actually, I just tried that and it didn’t work…same error.

      So, where do I put your code above into my code?

      • Daniel Freeman / Jun 3 2011 10:53 pm

        If you only need watername, just one label – you don’t need a custom item renderer….

        data.push({label:result.data[i].watername});

        “label” is important.

  13. Manx / Jun 3 2011 10:58 pm

    Awesome! That just made my weekend. Thanks for all your help! I’m sure I’ll be back for more…

  14. Sanad / Jun 4 2011 3:14 am

    There seems to be a problem with groupedList/navigation. When there are two lists in [navigation], clicking on any row in first list navigates to the second list even if you do not have an event listener for that. There might be cases when you need one group on the first list to navigate to the next list but for the second group, you want to do some thing different. In my case, I have a switch in the second group on the first list. (If you are wondering how I had achieved adding a custom renderer for second group, I just a set its visibility to false in the first group.)
    I have also logged another but at http://code.google.com/p/mad-components/issues/detail?id=1
    I am not sure if you saw it.

  15. Sanad / Jun 4 2011 3:20 am

    A question. It appears that when you have a customer renderer on a row in a list (I have TLFTextField), any clicks/taps on that renderer does not get recognized and the CLICKED event is not fired. Is there a way we can have a behavior similar to UILabel?

    • Daniel Freeman / Jun 4 2011 7:47 am

      It looks like I need to make some code changes to address the issues you’ve raised, and the issue logged on the Google site. I should be able to take a look at these this evening. (UK time)

  16. Adam Coburn / Jun 4 2011 4:32 pm

    Me again. Ok I have a list building in another class for jobs. I have passed through a sprite to add it to on initiation. The list adds fine and positions itself in the 0,0 of the sprite it was created on. What would be nice is if the list could take on the width and height of the sprite it was added to. Is there a way to do that? Like set the viewable window of the list. Mainly I am adding a list to a portion of the screen.

    If there is a way now, I missed it in the docs.

    Thanks again!

    • Daniel Freeman / Jun 4 2011 5:03 pm

      Not sure I understand the question. I think you’ve added the list in a Pure ActionScript way:-

      var list:UIList = new UIList(this, , new Attributes(0,0,320,480));

      In which case the 320, 480 parameters are the width and height. But the list isn’t masked. So you can see the list continuing above and below the list area. But you can apply a mask in the usual actionScript way if you like.

  17. rhinoseo / Jun 4 2011 5:41 pm

    Ok I got that part, but what appears to be happening is that say this list is 200 pixels high… even though it extends beyond… it does not behave like that 200 mark is the bottom of the scrollable window. If I scroll up or down it does the bounce back like I have reached the end regardless. I hope I explained that right.

    BTW… your e2publish app looks pretty sweet. I tried to download but there was only a download flash link, like I don’t have it.

  18. Daniel Freeman / Jun 4 2011 6:16 pm

    Check out version 0.4.3 for fixes to the issues raised here.

  19. Adam Coburn / Jun 4 2011 6:17 pm

    Does that count my issues with the scrolling?

    • Daniel Freeman / Jun 4 2011 6:36 pm

      I haven’t been able to reproduce this problem. Can you post some simple code that demonstrates it? Here, or on the issues section of the Google code site.

  20. Adam Coburn / Jun 4 2011 7:01 pm

    Sure Here it is:

    To do this… I created a class Jobs that houses the list info.

    on my main stage I did the following

    var compScreen:Sprite = new Sprite();

    addChild(compScreen);

    var jobs:Jobs = new Jobs(compScreen);

    compScreen is passed through the constructor as screen just like in you MadComponents example.

    //Inside Jobs class

    if (screen) screen.addChild(this); /// This is the 300 x 200 sprite I passed in

    //Populate the first list
    var data0:Array = [];
    for (var i=0; i<JOBS.length; i++) {

    data0.push({label:'’+JOBS[i]+”, image:getQualifiedClassName(ICONS[i%ICONS.length]), label2:’here is some small text’});
    }

    var uiList1:UIList = new UIList(this,LIST0,new Attributes(0,0,screen.width,screen.height));
    uiList1.data = data0;

    Now the list is posted to the stage in the sprite (screen that I passed in)

    I added 8 elements that makes the list extend past the 200 pixels. They all appear on the screen because I have not masked yet, but when I take my finger and scroll to the bottom of the list, it won’t scroll up… meaning the 200 pixels I set in the height of the list means nothing… the bottom of the list that I see, regardless of mask is the bottom of the list… not the 200 pixel mark I set.

    So I get that bounce back effect when I attempt scroll

    The list treats the bottom of the entire stage as the bottom of the scroll able window and the X and Y of the screen(sprite) I put it in as the top.

    To be sure, I added like 30 items to the list…. when they extend off the screen I can then scroll smoothly until the bottom of the list is at the bottom of my stage.

    I hope that makes sense 🙂

    • Daniel Freeman / Jun 4 2011 7:21 pm

      Where is compScreen set to 200×300 pixels? From what you’ve written above, it looks like it is empty. No pixels.

      But if you are setting the dimensions of compScreen somewhere – try tracing, or setting a breakpoint to look at screen.width and screen.height – see if they’re what you expect.

  21. Adam Coburn / Jun 4 2011 7:30 pm

    Hey, yeah sorry I was trying to keep the code short. the sprite is actually something from my SWC library and after tracing the height in indeed 300px

  22. Sanad / Jun 5 2011 5:12 am

    Thanks for the fixes. They work fine now.

    I have, however, logged to more bugs related to lists:
    1. UINavigation.nextPage(UIPages.SLIDE_LEFT) and UINavigation.goToPage(1, UIPages.SLIDE_LEFT) always navigates to last page when there are more than two pages in list
    2. UINavigation.navigationBar.rightButton does not work with UIButton.CLICKED listener with or without setting UINavigation.autoBack = false

    I was also wondering if the picker could have more inertia / fluidity in scrolling similar to that of a list? At present, it scrolls only a row up or down no matter how fast you try to scroll.

  23. Daniel Freeman / Jun 5 2011 6:21 pm

    I followed up the issues raised with Sanad and Adam, and we’ve manage to resolve these without changes to the MadComponents Library.

    Thanks to everyone who provided feedback, feature requests, and bug reports. You’ve helped to make MadComponents better. I’d be interested to see the outcome of some of these apps you’re working on.

    I’ve introduce better fluidity in UIPicker in the next update.

    In the meantime – keep the feedback coming!

  24. Sanad / Jun 8 2011 12:28 am

    Is there a way we can do list.data.push({label:”Some Text”}) instead of first creating an array and assigning it to list.data.

    Currently when I do list.data.push, I get “Access of possibly undefined property data through a reference with static type com.danielfreeman.madcomponents:UIList”

    This would be useful in cases when one needs to do some modification/formatting on the text in the same loop in which the text is added therefore avoiding to loop a second time just to format the text.

    I am using TLFTextField in my list of more than 100 rows. Right now, I do:

    var arr:array= new Array();
    for(var i:int=0; i<100; i++){
    arr.push( {label:"My text"});
    }
    list.data = arr;

    then,

    _textFormat.size = FONTSIZE;
    _textFormat.align = TextFormatAlign.LEFT;
    for (i=0; i< 100.length; i++) {
    _tlfTextField = TLFTextField(list.findViewById("label",i));
    _tlfTextField.mouseEnabled = false;
    _tlfTextField.selectable = false;
    _tlfTextField.setTextFormat(_textFormat);
    }

    It will be helpful I could get rid of the second loop and do the formatting/setting properties in the first loop.

    • Daniel Freeman / Jun 8 2011 7:49 am

      The formatting should be done inside the custom label component – shouldn’t it?

      Are you including the TLFTextField like this?:-

      [list xmlns:fltext=”fl.text”] [fltext:TLFTextField id=”label”/] [/list]; ?

      I’d make a new class, that extends TLFTextField, and sets the the formatting inside the object.

      public class MyLabel extends TLFTextField {

      public function TLFTextField() {
      mouseEnabled = false;
      selectable = false;
      var format:TextLayoutFormat = new TextLayoutFormat();
      format.fontSize = 24;
      defaultTextFormat = format;
      }

      } // I haven’t tested this code btw – it’s just off the top of my head.

      And include this custom class inside your item render instead.

      (Oh, I’ll look into the scrolling list click thing today)

      • Sanad / Jun 8 2011 10:01 pm

        Am I doing some thing wrong here?:
        [list id=”myList” xmlns:lbl=”com.abc.bookgeneral.components”]
        [horizontal]
        [lbl:BoldLabel id=”label” height=”30″ width =”400″ alignV=”center” alignH=”left”/]
        [image id=”image” alignH=”right”]24[/image]
        [/horizontal]
        [/list]

        Where path to BoldLabel is com.abc.bookgeneral.components.BoldLabel and I have com.abc.bookgeneral.components.* in an import statement

        I am getting:

        ReferenceError: Error #1065: Variable BoldLabel is not defined.
        at global/flash.utils::getDefinitionByName()
        at com.danielfreeman.madcomponents::UIForm/otherCommands()[/Users/danielfreeman/Documents/Adobe Flash Builder 4/MadComponentsLib/src/com/danielfreeman/madcomponents/UIForm.as:319]
        at com.danielfreeman.madcomponents::UIForm/parseBlock()[/Users/danielfreeman/Documents/Adobe Flash Builder 4/MadComponentsLib/src/com/danielfreeman/madcomponents/UIForm.as:148]
        at com.danielfreeman.madcomponents::UIForm()[/Users/danielfreeman/Documents/Adobe Flash Builder 4/MadComponentsLib/src/com/danielfreeman/madcomponents/UIForm.as:34]
        at com.danielfreeman.madcomponents::UIList/customRenderers()[/Users/danielfreeman/Documents/Adobe Flash Builder 4/MadComponentsLib/src/com/danielfreeman/madcomponents/UIList.as:299]
        at com.danielfreeman.madcomponents::UIList/set data()[/Users/danielfreeman/Documents/Adobe Flash Builder 4/MadComponentsLib/src/com/danielfreeman/madcomponents/UIList.as:168]
        ……

        NOTE: Using TLFTextField works fine as you have in your reply above:
        [list xmlns:fltext=”fl.text”] [fltext:TLFTextField id=”label”/] [/list]

      • Daniel Freeman / Jun 8 2011 10:22 pm

        You need to reference BoldLabel in your code. In my example, I do it like this:-

        protected static const USES:Array = [BoldLabel];

        It just ensures that BoldLabel is included when your project is compiled and linked.

  25. Sanad / Jun 8 2011 4:53 am

    I just noticed that when you are scrolling through a UIList, if you try to stop the scroll, a click is received on the row where the finger touched the screen. This would cause unintentional clicks when the purpose is to stop the scroll. A fix would be highly appreciated. Thanks.

    • Daniel Freeman / Jun 8 2011 3:25 pm

      I fixed this. It only took a couple of lines of code. Let me know if you need it in a hurry. Otherwise, I’ll wait until the next update to update the changes.

      • Sanad / Jun 8 2011 4:05 pm

        Depends on when the next update is scheduled. I can wait for a week to 10 days on this.

      • Daniel Freeman / Jun 10 2011 9:18 pm

        It’s in version 0.4.5 available now.

  26. Sanad / Jun 12 2011 10:01 pm

    I just updated to version 0.4.6 from 0.4.3

    I am facing this problem which I was not in 0.4.3:

    I am getting the following error on the second line of my code below:

    img = UIImage(list.findViewById(“image”, 0));
    img.imageClass = CHECK;

    where CHECK is defined as:

    [Embed(source=”/Images/check.png”)]
    protected static const CHECK:Class;

    Here is the error:

    ArgumentError: Error #2025: The supplied DisplayObject must be a child of the caller.
    at flash.display::DisplayObjectContainer/removeChild()
    at com.danielfreeman.madcomponents::UIImage/set image()[/Users/danielfreeman/Documents/Adobe Flash Builder 4/MadComponentsLib/src/com/danielfreeman/madcomponents/UIImage.as:69]
    at com.danielfreeman.madcomponents::UIImage/set imageClass()[/Users/danielfreeman/Documents/Adobe Flash Builder 4/MadComponentsLib/src/com/danielfreeman/madcomponents/UIImage.as:104]
    at com.danielfreeman.madcomponents::UIImage/set imageClassName()[/Users/danielfreeman/Documents/Adobe Flash Builder 4/MadComponentsLib/src/com/danielfreeman/madcomponents/UIImage.as:96]

    Please advise. Thanks.

    • Daniel Freeman / Jun 12 2011 11:41 pm

      … just stared at my code for ages – and realise where the problem could be, and why my tests didn’t catch it.

      I’ll correct this for 0.4.7, but I have a workaround for now:-

      If you always specify the size of the image – it shouldn’t crash. (Which is why the bug got past me).

      [image]40[/image] or [image]40,50[/image]

      (where the first defines an image 40×40 pixels, and the second defines 40×50 pixels – substitute your own image size).

      . . . . .. .

      update:- Nope. That wasn’t a bug. I’m not sure what’;s wrong. Can’t reproduce problem. The workaround I gave may work – also might try:-

      [image]{getQualifiedClassName(CHECK)}[/image]

      in XML. Or go back to v0.4.5 for now, until I work out the problem.

      Can you provide a simple test example?

  27. Sanad / Jun 14 2011 12:48 am

    I already had [image]20[/image] set in my XML. Also, I need to change the image on clicks (in runtime) so [image]{getQualifiedClassName(CHECK)}[/image] won’t work?

    Below is a test to reproduce the bug. I can send you the .as file if you provide me an email address. Thanks:

    package
    {
    import com.danielfreeman.madcomponents.*;

    import flash.display.Sprite;
    import flash.display.StageAlign;
    import flash.display.StageScaleMode;
    import flash.events.Event;
    import flash.utils.getQualifiedClassName;

    public class TestList extends Sprite {

    protected static const LIST0:XML = [list id=”list0″ colour=”#FFFFFF” background=”#CCCCCC,#FFFFFF”]
    [horizontal]
    [image id=”image”]48[/image]
    [vertical]
    [label id=”label”/]
    [label id=”label2″ height=”20″ alignH=”right”/]
    [/vertical]
    [/horizontal]
    [/list];

    [Embed(source=”images/mp3_48.png”)]
    protected static const MP3:Class;

    [Embed(source=”images/usb_48.png”)]
    protected static const USB:Class;

    protected static const FRUIT:Vector.[String] = new [String][“Apple”,”Orange”,”Banana”,”Pineapple”,”Lemon”,”Mango”,”Plum”,”Cherry”,”Lime”,”Peach”,”Pomegranate”,”Grapefruit”,”Strawberry”,”Melon”];

    protected var uiList1:UIList;
    protected var img:UIImage;
    public function TestList(screen:Sprite = null) {
    var i:int;

    if (screen)
    screen.addChild(this);

    stage.align = StageAlign.TOP_LEFT;
    stage.scaleMode = StageScaleMode.NO_SCALE;

    UI.create(this, LIST0);

    //Populate the first list
    var data0:Array = [];
    for (i=0; i[FRUIT.length; i++) {
    data0.push({label:'[font size=”18″]’+FRUIT[i]+'[/font]’, image:getQualifiedClassName(MP3), label2:'[font color=”#666666″ size=”11″]here is some small text[/font]’});
    }
    uiList1 = UIList(UI.findViewById(“list0”));
    uiList1.data = data0;
    uiList1.addEventListener(UIList.CLICKED, listClicked);
    }

    protected function listClicked(event:Event):void {
    trace(“Clicked: ” + uiList1.index);
    img = UIImage(uiList1.findViewById(“image”, uiList1.index));
    img.imageClass = USB;
    }

    }
    }

  28. Sanad / Jun 14 2011 12:50 am

    Is there away we can programmatically scroll a list to a certain index?

    • Daniel Freeman / Jun 14 2011 9:43 am

      The image test passes in 0.4.7 (which also has an index setter for lists, same as UIPicker). I’m still testing it – but it should be on the Google code site tonight.

    • Daniel Freeman / Jun 14 2011 9:53 pm

      There are two ways now to scroll a list (version 0.4.7):-

      1. list.scrollPositionY = value; // scroll value in pixels.

      2. list.index = rowIndexValue; // row index. – the row will be moved to the top of the scroll area.

      To set the index of a divided list or grouped list, set the group first. Eg:-

      list.group = 2;

      list.index = 3;

      • Sanad / Jun 14 2011 11:41 pm

        That works. Thanks.

        Is there a way I can programmaticaly set the title/heading of a group within a UIGroupList? I am not using XML to set my data.

  29. Sanad / Jun 15 2011 1:04 am

    I have a formatting question. In a UIGroupedList, I need to have two stacked labels on the left and a vertically centered arrow OR a vertically centered UISwitch on the right. Here is what I have right now:

    [groupedList id=”groupedList” background=”#c6d6c7,#FFFFFF” colour=”#CCCCCC” gapH=”32″ gapV=”4″ xmlns:lbl=”com.shlinfosystems.bookgeneral.components.ListLabels”]
    [horizontal]
    [vertical]
    [lbl:HeadingLabel id=”label1″ height=”30″/]
    [lbl:DetailLabel id=”label2″ height=”30″/]
    [/vertical]
    [arrow id=”arrow” colour=”#334433″ background=”#CCCCBB,#999988″ alignH=”right” alignV=”center”/]
    [switch id=”switch” colour=”#006600″ visible=”false” alignH=”right” alignV=”center”]Auto,Off[/switch]
    [/horizontal]
    [/groupedList];

    but both, arrow and switch (with I make visible in runtime) appear on top right. It seams like alignV=”center” is not working as expected or I am doing some thing wrong. Please advise.

    • Daniel Freeman / Jun 15 2011 8:45 am

      British spelling. “centre”.

      UIGroupedList doesn’t have titles/headings. UIDividedList does. You can make the top cell in each cell a different colour from the rest. But if you need titles above each group – this would be a feature request. How badly do you need it?

      • Sanad / Jun 15 2011 9:51 am

        It will be a “nice to have”. If am going to have it, I will need to use a TLFTextField for the label. However, I can do with the first cell in different color. How can I do that in code? and can I also make the first row unclickable? (Not even change color on clicks/taps)

      • Daniel Freeman / Jun 15 2011 6:10 pm

        Ok, I’ve given you group headings in UIGroupedList version 0.4.8. What’s more, I’ve given you a way to use a particular class or DisplayObject instead of a label.

        eg:-

        var myTLFinstance = new TLFTextField();
        //assign stuff, set it up.

        list.data = [myTLFinstance, [{label:”one”},{… etc…..

        in XML, you can say:-

        protected static const GROUPED_DATA:XML = [data]
        [group icon={getQualifiedClassName(MYCLASS)}]… etc…

  30. Sanad / Jun 15 2011 10:57 pm

    That’s awesome.

    I did find an issue though. UI.findViewById() is not returning the right element after the 0.4.8 update. I have logged an issue for it.

    Thanks.

    • Daniel Freeman / Jun 17 2011 9:14 am

      Fixed in 0.4.9. Thanks for finding these bugs.

      • Sanad / Jun 17 2011 5:55 pm

        Just trying to give something back. And the fact that I’ve been a software tester for the past 3 years is helping.

        Any updates on adding fluidity to the picker? I badly want to move away from as3flobile.

      • Daniel Freeman / Jun 17 2011 9:20 pm

        I made code changes to make it more fluid. I guess I need to fine tune the parameters. I just did a test, switching between it and the XCode real picker. Simulating on the desktop it seemed more fluid, but more sluggish on my iPod.

        I’ll try and get it right over the weekend.

  31. Sanad / Jun 17 2011 8:46 pm

    Just logged another bug:

    :ReferenceError on UINavigation.goToPage() when clicking first group only”

    Might be related to the bug 6 you just fixed.

  32. Sanad / Jun 18 2011 5:23 am

    A couple of questions.
    1) There was a mention of changing click color on list in one of the update descriptions. But that has been overwritten. Can you please describe it again?
    2) Is it possible to make backgrounds transparent (especially, that of a list)?
    3) Is it possible to have TLFTextField for the UINavigation title?

    Thanks.

    • Daniel Freeman / Jun 18 2011 8:06 pm

      Good questions.

      1) In the root XML node (the one you pass to UI.create()), there are a few settings you can specify. I’ve never documented these, so I should do that now.

      for example:-

      [vertical stageColour=”#CCCCCC” clickColour=”#999999″ dpi=”150″ autoScale=”false” autoResize=”false”]….etc….

      stageColour is the colour of the background.
      clickColour is the highlight colour when you click on a list or skinned button.
      dpi is the nominal screen resolution in pixels per inch. MadComponents adjust scaling to achieve this resolution, whatever the resolution of the device might be.
      autoScale=”false” switches off this scaling adjustment
      autoResize=”false” switches off the refreshing the UI when screen orientation changes.

      2) In version 0.5, (which I’ll upload tonight) I’ve made that the default.

      3) uiNavigation.navigationBar is a subclass of Sprite. So you can addChild() whatever you like to it. But if you do – you have to write your own code to centre it when the orientation changes.

      Let me know what you think of the fluidity of the picker when you see the new version.

      • Sanad / Jun 19 2011 4:59 am

        I am experiencing some very strange behavior in version 0.5. This was not happening in 0.4.9
        In my app, I have two places where I do UI.create(). The second creation messes up the first one. (The first one works perfectly fine until the second is created). It does not matter which one is created first. By mess up, I mean odd behaviors like embedded images not appearing, the interface not adjusting to orientation change properly, disappearing of the contents of a UINavigation and getting “RangeError: Error #2006: The supplied index is out of bounds.” when trying to do UI.findViewById() and providing a row index that is supposed to work.

      • Daniel Freeman / Jun 19 2011 7:02 am

        I’m surprised it ever worked. It was deigned to remove the first UI if a second UI is created. Take things off the display list, remove all listeners, etc.

        Is it possible to create just one? Maybe as two pages?

        var LAYOUT:XML = [pages id=”pages”] {MY_UI1} {MY_U!2} [/pages];

        . . .

        _pages.goToPage(1);

      • Sanad / Jun 20 2011 4:28 am

        Things are working well with Single UI.create(). I have not got a chance yet to test the new picker changes. Logged another bug related to list background and color with pure AS.

  33. sanad / Jun 20 2011 8:50 pm

    Is there a way to have different height values for different rows in a list?

    • Daniel Freeman / Jun 20 2011 9:17 pm

      Yes. If you say [list autoLayout=”true/] then list rows may be different heights. Take a look at the Twitter example. (MadComponentsJSON.as)

      Heights are recalculated whenever data is changed. You can force a list layout to refresh with the method .doLayout();

      By the way, if you set alignH=”fill” or set the width of a label, then it becomes a multiline label, and variable height.

      What you DON’T have in MadComponents is an includeInLayout attribute, like you have in MXML. (So even if an object is not visible, it’s height is still included).

  34. sanad / Jun 20 2011 9:23 pm

    For a UIList or UIScrollVertical, is it possible to restrict the content visibility within the bounding box defined by Attribute?
    When a UIList/ UIScrollVersical is created with pure AS and placed, for example, in the center of the screen and scrolled, the contents are visible even after they pass out of the defined boundary of the UIList.

    • Daniel Freeman / Jun 20 2011 9:28 pm

      The only way I can think of is with your own class which incorporates masking, and also override function get height():Number {… etc….

      …wait.. lists, and scrollVertical are sprites. They have a mask property, you can assign to in ActionScript. I don’t use ScrollRect (maybe I should have) – but nothing to stop you using that either to do your own masking.

      • Sanad / Jun 21 2011 5:53 pm

        I will give it a try. Thanks for the info.

  35. sanad / Jun 21 2011 5:50 pm

    A couple of thought about the picker:
    1. The fluidity is now very good but has a few quirks. When the picker is in full swing, if you try to stop it by just tapping it, it stops and then starts again in slow speed. The intention here is to just stop the picker completely.
    2. It is difficult to move to the next top or the next bottom row. The sensitivity makes the picker roll more than expected.
    3. My major concern is the time it is taking to set the index to a particular position. I have a picker with four columns. The first one has around 600 rows, the second and third ones are around 100 rows and the fourth is 30 rows. The selection of a row in one columns triggers the setting of index in all remaining three columns. The update is taking between 4-8 seconds compared to 1-2 seconds in as3flobile.
    4. When we set picker.index, is it possible to have it animate to the row?

    • Sanad / Jun 21 2011 6:22 pm

      Ok. I have to retract my points 1 and 2 above after looking at the pickers in MadComponents0_5.apk
      For some reason, The pickers in my app are not as large in height as those in MadComponents0_5.apk. The small height seam to be the reason I am not getting the same experience as inMadComponents0_5.apk.
      No matter what I do, I am not able to change the height. I am creating the picker in pure as:

      protected static const PICKER:XML = [columns widths=”15%,15%,55%,15%” gapH=”0″ background=”#9999AA” xmlns:lbl=”com.bookgeneral.components.ListLabels”]
      [picker id=”picker1″ autoLayout=”true”]
      [lbl:PickerLabel id=”pickerLabel1″ height=”40″ alignH=”fill” alignV=”fill”/]
      [/picker]
      [picker id=”picker2″ autoLayout=”true”]
      [lbl:PickerLabel id=”pickerLabel2″ height=”40″ alignH=”fill” alignV=”fill”/]
      [/picker]
      [picker id=”picker3″ autoLayout=”true”]
      [lbl:PickerLabel id=”pickerLabel3″ height=”40″ alignH=”fill” alignV=”fill”/]
      [/picker]
      [picker id=”picker4″ autoLayout=”true”]
      [lbl:PickerLabel id=”pickerLabe4″ height=”40″ alignH=”fill” alignV=”fill”/]
      [/picker]
      [/columns];

      pickerForm = new UIForm(this, PICKER, new Attributes(0,0, stage.stageWidth,PICKERHEIGHT));

      PICKERHEIGHT does not change any thing. The height is always same.

      • Daniel Freeman / Jun 21 2011 6:37 pm

        I’ll see what I can do about being able to set the height (shouldn’t be too difficult to code). And animating to a specific index

  36. danial / Jun 22 2011 11:43 am

    wre is the download link for version 0.4.5?

  37. Brady / Aug 9 2011 12:11 pm

    Hi Daniel,
    I am new to madcomponents and fairly new to flex, although have a c and java background. Is it possible to integrate osmf into the madcomponents in any way, perhaps an example of how to integrate other libraries? (whilst you have your own charts, what about the fusioncharts..)

    I really like what you are doing with madcomponents..

    Brady.

    • Brady / Aug 10 2011 12:13 am

      Apologies for posting this to the wrong topic. In addition using your placeholder image and attaching the MediaPlayerSprite works (well on the desktop, just need to test on the device..)

  38. colepeterson / Sep 8 2011 5:08 am

    I can’t seem to change the color of a ui list in a pure as version.
    I get no bg color.
    any thoughts?

    var myLIST:XML =

    {SMALL_TEXT}

    var list:UILongList = new UILongList(_holder, myLIST, new Attributes(0,10,320,768));

  39. colepeterson / Sep 8 2011 5:10 am

    oh sorry all my xml got stripped. my xml has a value for background.
    background=”#CCCCFF,#9999CC,#AAAACC”

    is there a way to do something like
    list.backgroundColors = new Vector ……

    Just set it.

    thanks
    cp

  40. Donny / Sep 10 2011 5:40 am

    Hi Daniel,

    Can you please give an example of how to use the popUp with pure as3?

    I have defined:

    protected var disclaimerPopUp:UIWindow;

    and defined the XML:

    protected static const DISCLAIMER_POPUP_WINDOW:XML =

    Decline
    Accept

    ;

    then try create it with:

    disclaimerPopUp = UI.createPopUp(DISCLAIMER_POPUP_WINDOW,180.0,200.0);

    But that gives the following error:

    Main Thread (Suspended: TypeError: Error #1009: Cannot access a property or method of a null object reference.)

    • Donny / Sep 10 2011 5:45 am

      d’oh – xml got stripped 😦

      have taken the less than sign out: should be:

      protected static const DISCLAIMER_POPUP_WINDOW1:XML =
      vertical alignH=”fill”>
      columns>
      button colour=”#669966″ id=”Decline”>Decline/button>
      button colour=”#996666″ id=”Accept”>Accept/button>
      /columns>
      /vertical>;

    • Daniel Freeman / Sep 10 2011 3:37 pm

      I just copied and pasted in your code – and it worked for me. No error.

      http://code.google.com/p/mad-components/source/browse/trunk/MadComponentStuff/src/MadComponents.as has an example.

      Did you do it after the UI.create(…. ?

      If you still have problems, I’ll take a look at the code.

      • Donny / Sep 12 2011 8:54 am

        aha – didn’t realise I had to call that method – thanks.

        I got it working by calling it with some dummy xml as my stage layout is done outside of MadComponents – unless you’d recommend a better way?

        protected static const DUMMY_LAYOUT:XML = vertical></vertical;

        UI.create(this, DUMMY_LAYOUT);

        disclaimerPopUp = UI.createPopUp(DISCLAIMER_POPUP_WINDOW,180.0,200.0);

  41. Donny / Sep 18 2011 12:25 am

    Hi Daniel,

    Any chance you’d be able to point me in the right direction with regards to setting the selected / not selected colors on a UISegmentedControl in pure as3? Here’s my current code:

    private const SEG_DATA:XML = data> units label=”label1″/>
    units label=”label2″/>
    units label=”label3″/>
    /data>;

    UISegCtrl = new UISegmentedControl(this, SEG_DATA, new Attributes(0,0,250,50));

  42. adrian s / Dec 7 2011 5:44 pm

    I’m trying to make a very simple textfield with a height of stage height.
    And put it inside a scroller, so when you type too much into it, you can scroll around.

    Can’t get this to work.

    Here is what I’ve tried:
    protected static const SCROLLER:XML =

    • Daniel Freeman / Dec 8 2011 6:07 am

      I’m afraid wordpress strips out xml tags. Try again with [ and ] instead of lt and gt.

  43. wilsmex / Dec 14 2011 6:51 am

    Stuck on something I’m thinking should be simple here…

    Trying to create a UIForm with various textfields and whatnot via your UIFormMaker helper…

    I want to then “attach” that to a UIScrollVertical instance, so I can scroll up and down the content of the UIForm.

    Is this possible? I can’t seem to get this working. Just digging through the various classes and trying to logically put this together based off what the classnames tell me those components do…

  44. xavb / Oct 21 2013 9:46 pm

    hello, very good job !
    I want add a mad-component button over my scene wich contains interactives clips, but my clips don’t detect mouse events, hidded by the ui. I tried with mouseEnabled, mouseChildren to change that but no way.
    Is there a solution ?

Trackbacks

  1. @renaun posts: Designing and Skinning Mobile Applications Link Roundup

Leave a reply to Brady Cancel reply