Skip to content
June 23, 2011 / Daniel Freeman

Tutorial 2: Images, and Nine Patch Images in MadComponents

In the first tutorial, we built a simple two page application with a button on each page, which triggered a page change.  The tutorial was an interpretation of “Build a mobile app in five minutes“.  But instead of building the project in Flash Builder 4.5, we built it using MadComponents.  It is recommended to read the previous tutorial to get the most out of this tutorial.

MadComponents is IDE agnostic.  So you can build mobile projects in Flash, or Flex (Flash Builder), or third-party Flash Platform tools.

In this tutorial, we’re going to learn about images, skinning, and nine patch images in MadComponents.

This tutorial assumes you have version MadComponentsLib0_5_1.swc or a later version.  Download it from http://code.google.com/p/mad-components/downloads/list

The image tag

We can include images into a MadComponents layout using the <image> tag.  For example:-

<image>{getQualifiedClassName(PICTURE64)}</image>

This layout just includes the image class “PICTURE64” into your layout.  getQualifiedClassName is an Adobe utility that coverts a Class reference to a textual representation. Here is the complete program:-

package
{
	import flash.display.Sprite;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;
	import flash.utils.getQualifiedClassName;

	import com.danielfreeman.madcomponents.*;

	public class MadImage extends Sprite
	{
		[Embed(source="images/picture64.png")]
		protected static const PICTURE64:Class;

		protected static const IMAGE:XML = <image>{getQualifiedClassName(PICTURE64)}</image>;

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

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

			UI.create(this, IMAGE);
		}
	}
}

picture64 is your own .png image file. (Assumed to be 64×64 pixels). We assume we’ve put in in a folder called images.

Beware Copy And Paste

The following general advice isn’t only applicable to MadComponents project.  It is a general issue, that can affect any project.

Copying and pasting into Eclipse, or Flash can cause inexplicable errors in your code.  Especially code that has XML.   Working through a tutorial such as this, you’re likely to copy and paste.  The problems are caused by unprintable characters in the pasted code.  They look like spaces, or linefeeds, but they’re not.  And they screw things up.  If this happens, one way you can fix things is to delete all the spaces and linefeeds, and then reformat your code or layout xml.  Single, and double quote characters can also cause problems.  There are several versions of these characters, that look very similar – but the wrong character will cause a syntax error.

MadComponents provides a utility, UI.clean() that removes unwanted unprintable characters in XML layouts.

Instead of writing this:-

UI.create(this, LAYOUT);

Write this:-

UI.create(this, UI.clean(LAYOUT));

The reason that clean isn’t employed usually, is that there is an overhead to doing this.  If you run into problems, it is better to try and delete spaces, linefeeds, and reformat.  But UI.clean() is an easy thing to do if you run into copy paste problems during development.  And it can help eliminate this as a possibility when debugging your code.

Set image from ActionScript

You can use an image tag to define an empty placeholder for an image that you assign in ActionScript.  For example, here is an placeholder for an image 64 pixels by 64 pixels:-

<image id=”myimage”>64</image>

If you specify one number, the placeholder is assumed to be square.  But specify two numbers for a rectangular place holder, for example, 30 pixels (width) by 40 pixels (height):-

<image id=”myimage”>30,40</image>

To assign an image to this placeholder, use the following code:-

var myImage:UIImage = UIImage(UI.findViewById(“myimage”));

myImage.imageClass = PICTURE64; //Where this is the embedded Class from before.

Or you can write:-

myImage.imageClassName = getQualifiedClassName(PICTURE64);

If the placeholder size is smaller than the image size, then MadComponents will scale the image down to fit.

You can also set the image from a bitmap instance.  This is convenient for developers using Flash, as they can utilise an image that they’ve set up in their library.

myImage.image = bitmapValue; //From Flash Library.

You can assign any DisplayObject subclass instance to the image property.

myImage.image = anyDisplayObjectSubclassInstance;

Suppose you want to assign a different image to a placeholder, depending on the screen density of the device.  You might do something like this:-

var dpi:uint = Capabilities.screenDPI;

if (dpi>280)

myImage.imageClass = PICTURE64_320;

else if (dpi>200)

    myImage.imageClass = PICTURE64_240;

else

    myImage.imageClass = PICTURE64_160;

Here is an example with an image that changes every time you click on it.  (Make sure you have MadComponentsLib0_5_1.swc or higher)

package
{
	import com.danielfreeman.madcomponents.*;

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

	public class MadImage extends Sprite
	{
		[Embed(source="images/mp3_48.png")]
		protected static const MP3:Class;

		[Embed(source="images/mp4_48.png")]
		protected static const MP4:Class;

		protected static const IMAGE:XML = <image id="myImage" alignH="centre" alignV="centre">
			{getQualifiedClassName(MP3)}
		</image>;

		protected var _myImage:UIImage;
		protected var _toggle:Boolean = true;

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

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

			UI.create(this, IMAGE);

			_myImage = UIImage(UI.findViewById("myImage"));
			_myImage.addEventListener(MouseEvent.MOUSE_UP,clicked);
			_myImage.mouseEnabled = true;
		}

		protected function clicked(event:MouseEvent):void {
			_toggle = !_toggle;
			_myImage.imageClass = _toggle ? MP3 : MP4;
		}
	}
}

ImageLoader

We can use an <imageLoader> to obtain an image from the server.  For example:-

<imageLoader>http://www.myserver.com/myImage.jpg</imageLoader&gt;

We can also define a placeholder.

<imageLoader id=”myImage”>40,30</imageLoader>

Control the <imageLoader> from ActionScript, as follows:-

var myImage:UIImageLoader = UIImageLoader(UI.findViewById(“myimage”));

myImage.value = “http://www.myserver.com/myImage.jpg&#8221;;

You can set up listeners on the UIImageLoader instance for Event.COMPLETE, SecurityErrorEvent.SECURITY_ERROR, IOErrorEvent.IO_ERROR, and ErrorEvent.ERROR.

Nine Patch Images

MadComponent buttons are skinnable.  We can use utilise a snazzy button design in the form of a .jpg, or .png image.  The size of the button may vary, for different screens, and depending on device orientation.  So the skin image must be resizable.  But when you resize an image, this can cause problems with pixelation and distortion of the bitmap.  The solution to the problem is called a “nine patch image”.  Some Flash developers reading this tutorial will be familiar with the concepts of nine patch images, but if you’re not – keep reading.

Suppose we have a snazzy button image:-

Now let’s resize the image vertically.

Now our button doesn’t look so snazzy any more.  The curved corners, and the corners of the highlight area are irregular and stretched.  There is a beveled area around the button, that’s looking very fat at the sides.  And I’m beginning to see pixelation raggedness on the curves.

Here is the same image vertically stretched, but this time, we’ve used a nine patch scheme:-

See the difference?  So how does nine patch scaling work?

We divide the image into nine regions.  Each region has different scaling rules.

In the corners (1, 3, 7 and 9 ) there is no scaling.  The sides ( 4 and 6 ) are only scaled vertically.  The top and bottom ( 2 and 8 ) are only scaled horizontally.  The centre ( 5 ) is scaled both horizontally and vertically.

We apply the nine patch to the red button image as show:-

The curved corners aren’t scaled, so their shapes are preserved.  The sides are scaled so that the bevel doesn’t get fat, and the highlight area of the button doesn’t get any taller.

In ActionScript, you can define a nine patch embedded image like this:-

[Embed(source="images/red.png",
      scaleGridTop="100", scaleGridBottom="200",
      scaleGridLeft="40", scaleGridRight="200")]
protected static const RED:Class;

Where scaleGridTop, scaleGridBottom, scaleGridLeft, and ScaleGridRight are the positions of the dividing lines of the nine patch (from the top-left corner).

Skinning a button

You can apply this nine patch image skin (or just a normal image) to a button within the layout like this:-

<button skin={getQualifiedClassName(RED)}>hello</button>

To set the height of a skinned button, you can use the height attribute:-

<button skin={getQualifiedClassName(RED)} height=”100″>hello</button>

You can also set a button skin in ActionScript:-

var button:UIButton = UIButton(UI.findViewById(“button”));

button.skinClass = RED;

//or

button.skin = getQualifiedClassName(RED);

button.skinHeight = 100.0;

Further reading

To find out more about MadComponents, you can read the other related threads on this blog, or download the documentation at http://code.google.com/p/mad-components/downloads/list

Please subscribe to this blog if you want to catch subsequent tutorials.

What’s next?

So far, we’ve barely scratched the surface of MadComponent’s capabilities.  In the next tutorial, we’ll be talking about lists and pickers.  Then we’ll build a Twitter client like the one described in this Flash Builder 4.5 tutorial.  But using MadComponents, it will be much, much easier than Flash Builder.

Advertisements

57 Comments

Leave a Comment
  1. Richard Tolley / Jun 27 2011 6:49 pm

    I’ve been following Mad Components with interest since the oringal release.

    I just want to congratulate you on a great bit of work. After playing around with the code samples and expirementing I now fully appreciate the benefits.

    10/10 – your work is really appreciated.

    For what it’s worth I have a proof of concept running using Mad Components running on Android, iOS, Blackberry Playbook, Desktop and Web. It works flawlessly.

    Regards

    Rich

  2. Richard Tolley / Jun 28 2011 12:49 am

    I need to replicate the contact screen of an iPhone and I’m struggling to say the least.

    With total abuse of the data and a grouped list I can sort of emulate what I’m after but there just has to be a better way.

    Ideally some sort of form container rounded corners top and bottom that I can drop labels/inputs buttons into it.

    Also – I love the rightButton feature – is there a leftButton too? I guess I’m being lazy – will try myself.

    If it’s already possible to acheive a similar layout to that of the iphone contact screen is there any chance of a small bit of sample code to show what would look like two short grouped lists on 1 screen with a three buttons underneath?

    Best Regards

    Rich

    • Daniel Freeman / Jun 28 2011 5:44 pm

      You’re right. Making a UI that looks like the contact screen isn’t too easy right now. I’ll see what I can do in version 0.5.2. (soon). I’ll get back to you on this.

      There is a left button. Usually it appears, and works automatically. But if you want to turn off its default operation, you can use the autoBack property, and make it visible yourself.

      var uiNavigation:UINavigation = UINavigation(UI.findViewById(“nav”));
      uiNavigation.autoBack = false;
      uiNavigation.navigationBar.backButton.visible = true;

      • Richard Tolley / Jun 28 2011 7:19 pm

        That’s great news about enhancements for 0.5.2 – I will concerntrate on the back-end for the time being.

        Thank you. Can’t wait to try it out.

        Rich

      • Daniel Freeman / Jun 29 2011 11:12 pm

        Hi Rich,

        0.5.2 is ready. You can take a look at the MadGroups.as example on the code site. Let me know if it solves your problems.

      • Richard Tolley / Jun 29 2011 11:35 pm

        Hi Daniel

        Thank you. I’m checking it out now.

        Will give you an update later.

        I’m going to have to spend some time blogging about MC. They are amazing.

        Rich

  3. Richard Tolley / Jun 28 2011 1:45 am

    Is it possible to have more than 1 grouped list on a screen at a time?

    Rich

  4. Richard Tolley / Jun 30 2011 1:33 am

    It’s superb – love it.

    I think I’ve found a minor bug – have logged it at google rather than clog up the blog.

    One question – I’m not sure if it’s my lack of understanding or a change in behaviour but …

    The striped background – On my grouped list the bars are vertical – on the clickableGroups they are horizontal. It would be nice to be able to make them all vertical or all horizontal (prefer vertical personally)

    Once again – superb work.

    Rich

    • Daniel Freeman / Jun 30 2011 8:20 pm

      Bug fixed in 0.5.3. You can now make yourself a vertically striped background too. In your example you attached to the bug log, you can remove the outer [vertical] … . And put the following parameters on the [scrollVertical] :-

      [scrollVertical id=”vScroller” background=”#E9E9EF,#EFEFEF,8,0″ colour=”#CCCCCC”]

      The fourth parameter to background, is the angle of rotation in degrees of the repeated gradient. So if diagonal stripes ever came into fashion – you could have them too.

      • Richard Tolley / Jul 5 2011 2:54 pm

        Hi Daniel

        A bit more feedback – first off – 99% of it is GREAT!

        I’m not sure whether this is a bug or a feature request.

        ClickableGroup – three columns – label – switch – arrow

        I want to display data, have a Yes/No switch with the option of moving to a details screen

        If I use ClickableGroup the switch never receives the mouse events – If I use a group the switch works but I can’t get a click event on the arrow (maybe I’ve got an error in my code)

        I tried adding a MouseEvent.MOUSE_UP event listener to the arrow – I just get an AS error.

        Are you ok with me leaving comments on here – I’m enthusiastically building my first App with Mad Components – I have a lot of feedback to give but I don’t want to clog your blog up.

        Regards

        Rich

      • Daniel Freeman / Jul 5 2011 4:43 pm

        I think comments like these are mostly useful to other readers. I’m happy about the clog. Specific bug requests can go on the Google code site if you like.

        I couldn’t duplicated the AS error. I used group, not clickableGroup. But the trick was to make the arrow mouseEnabled.

        var uiArrow:UIArrow = UIArrow(UI.findViewById(“arrow”));
        uiArrow.mouseEnabled = true;
        uiArrow.addEventListener(MouseEvent.MOUSE_UP, clickedHandler);

        You can change its appearance too with background:-

        [arrow arrow id=”arrow” alignH=”right” background=”#CCCCCC,#999999″ /]

        But there are things about the groups that I need to tidy up. The 1%. I’m still thinking about how to best solve these.

        My own wish-list for the next update includes the following:-

        1. I want to be able to centre things vertically inside a group, the same as I would inside a groupedList.

        2. I want arrow to be clickable inside a clickableGroup – enabling a list to link to two levels of detail.

        3. I want “hint” text with input. For example “surname” in light grey, but disappears when you enter text.

        So if there’s anything you want to add to my wish list – suggestions welcome, and keep the feedback coming.

      • Richard Tolley / Jul 5 2011 6:50 pm

        ok – mouseEnabled was the key 🙂

        Didn’t want to ask about vertical alignment – thought I would spread out my requests but that’s a big one. Like the iPhone contact screen I have group with each row having two/three columns – data label, label, arrow – in the case of something like an email address I want to use a smaller font – the vertical alignment runs out – I figured I could live with it for the time being.

        Arrow inside of clickable group – wanted 🙂

        A prompting option would be great for inputs.

        I would like a few bits tidied – this isn’t really a bug just different behaviour.

        outside of a clickableGroup if I have two columns with the first column say width 70 and I want to right align text I use

        {LABEL_TEXT}
        {LABEL_DATA}


        you MUST specify the width attribute otherwise it doesn’t appear to work correctly.

        inside a clickableGroup

        {LABEL_TEXT}postcode
        {LABEL_DATA}


        you MUST NOT specify width on the column otherwise it will not work.

        I can see the logic of both but it can be confusing.

        I would love a little more detail in the documentation – most of it is obvious but things like the mouseEnabled I wasn’t aware about.

        Regards

        Rich

      • Richard Tolley / Jul 5 2011 7:51 pm

        Hi Daniel

        I’m really struggling to get the arrow to be clickable.

        The issue I have is that UI.findViewById(“theArrow”) isn’t finding the arrow 😦

        little code block.

        {LABEL_TEXT}investments
        YES,NO

        var investDetails1:UIArrow = UIArrow(UI.findViewById(“tmdInvestDetails”));
        investDetails1.mouseEnabled = true;
        investDetails1.addEventListener(MouseEvent.MOUSE_UP, showInvestmentDetails);

        I always get a #1009: Can’t access a property or method of a null object reference.

        My feeling is that I need to find the group and then the arrow within the group – I just can’t figure out how to do this.

        Any chance of a pointer.

        Thanks

        Rich

      • Richard Tolley / Jul 5 2011 7:53 pm

        Grrrr – I’ll work out how to paste code at some stage.

        try again.

        <group id="tmd_investGroup" alignH="right" gapV="30">
        <columns widths="85,100%,20" gapH="5">
        <label id="tmd_lblInvestments" alignH="right">{LABEL_TEXT}investments</label>
        <switch id="boolInvest" alignH="centre">YES,NO</switch>
        <arrow id="tmdInvestDetails" colour="#666666" background="#ccccbb,#999988" alignH="right"/>
        </columns>
        </group>

        var investDetails1:UIArrow = UIArrow(UI.findViewById(“tmdInvestDetails”));
        investDetails1.mouseEnabled = true;
        investDetails1.addEventListener(MouseEvent.MOUSE_UP, showInvestmentDetails);

      • Daniel Freeman / Jul 5 2011 8:05 pm

        I tried that – but it worked. I omitted {LABEL_TEXT} that’s all. It’s a long shot but try UI.create(this, UI.clean(LAYOUT));

        Otherwise, I’m sending you an email, and you can attach you code for me to look at.

  5. Richard Tolley / Jun 30 2011 10:36 pm

    OK – you’re a hero!

    I don’t suppose there is any chance that you’re intending to add a calendar control in a future release?

    Something that gives a month view?

    Failing that, are you aware of any calendar components that exist that I could use with MCs?

    Rich

    • Daniel Freeman / Jun 30 2011 10:46 pm

      No plans to make a calendar component – but there should be an existing component – somewhere – I guess. It’s easy to integrate MadComponents with third-party stuff.

      https://madskool.wordpress.com/2011/05/11/using-madcomponents-with-minimalcomps-or-flobile-libraries/

      Or another technique is to define an empty placeholder in the layout, then:-

      var placeHolder:UIImage = UIImage(UI.findViewById(“placeHolder”));
      placeHolder.addChild(myCalenderComponent);

      • Richard Tolley / Jun 30 2011 11:17 pm

        Could this technique be used to embed a camera feed into an MC ui?

        Currently I have an app that I want to migrate to MC to improve the interface and reduce file size.

        I use something along the lines of

        var ui:UIComponent = new UIComponent();

        var cam:Camera;

        var video:Video = new Video(scrX, scrY);

        cam = Camera.getCamera();

        if (cam)
        {
        var video:Video = new Video(scrX, scrY);

        cam.setMode(cameraWidth, cameraHeight, cameraFPS);
        cam.setQuality(cameraBandwidth, cameraQuality);
        cam.setKeyFrameInterval(12);

        video.attachCamera(cam);
        ui.addChild(video);
        cameraGroup.addElementAt(ui,0);

        }

        using your example above

        could I do something like placeHolder.addChild(video)

        As video has to be wrapped in a UIComponent to add to stage would I get away with it or could I use something like

        placeHolder.addChild(ui);

        It’s rough hacked out code as an example so probably wouldn’t compile but is the thinking correct?

        BTW – Thank you for taking the time to answer my questions – it’s not expected but gratefully received.

        Rich

      • Daniel Freeman / Jul 1 2011 7:30 am

        As far as I can tell that should work. It would make for something informative to blog about if you did it.

    • Daniel Freeman / Jun 30 2011 11:07 pm

      You could make a date picker using a picker bank.

      • Richard Tolley / Jun 30 2011 11:12 pm

        I think that’s what I’m going to end up doing – maybe see if I can create some sort of dynamic text field at the top showing full date including day. Just need to do it intelligently and not overload the processor.

      • Richard Tolley / Jun 30 2011 11:20 pm

        BTW – I’m in the Flashbuilder pre-release programme – didn’t notice you in any of the posts – are you part of it?

        It’s more or less over now, I’ve got a couple of contacts at Adobe who have been very helpful – if you’re not part of the programme, would you like me to try and get you invited to the next one?

        Rich

      • Daniel Freeman / Jul 1 2011 7:28 am

        I’ve never been sold on the IDEA of Flex for mobile. I’m still on a few of Adobe’s prerelease programmes. I’ve been evaluating and following Burrito/Hero – but I haven’t commented.

  6. Richard Tolley / Jul 6 2011 2:36 pm

    So clickableGroup and Group are great.

    I’ve finished laying out the UI for the time being and I’m writing the code now.

    When you get a few minutes can you point me in the right direction of handling clicks from clickableGroup please.

    I’ve tried just about everything I can think of. My current code is looking something like this.

    protected static const TODAY_LIST_SORT_DRAWER:XML =

    <vertical alignV="fill" alignH="fill" background="#C5CCD4,#CBD2D8,10,0" colour="#ABABAB" gapV="5">
    <label>Set Today List Sort Order</label>
    <clickableGroup id="todayListSortGroup" gapV="25">
    <label id="todaySortList_FName">{LABEL_DATA}First Name</label>
    <label id="todaySortList_LName">{LABEL_DATA}Last Name</label>
    <label id="todaySortList_Status">{LABEL_DATA}Status</label>
    </clickableGroup>
    </vertical>;

    var todaySortList1:UIForm = UIForm(UI.findViewById(“todayListSortGroup”));
    todaySortList1.addEventListener(UIForm.CLICKED, sortTodayList);

    protected function sortTodayList(e:Event):void
    {

    var uf:UIForm = UIForm(UI.findViewById(“todayListSortGroup”));
    var index:int = uf.index

    trace(“sortListClicked: ” + index);

    _navigator.goToPage(0);
    navigatorChange();
    }

    How do i find out which item within the group was clicked?

    The code above sort of works but first click I get an index of -1 an subsequent clicks only seem to return the correct index now and again.

    I’ve been banging my head against the wall for a couple of hours now and it’s starting to get sore.

    Regards

    Rich

    • Daniel Freeman / Jul 6 2011 2:49 pm

      Sorry about the headache. My fault – Doh!!! I did something really stupid. I’ve dispatched the event BEFORE I set the state of index. I’ll add it to the 0.5.4 to-do-list. Thanks for catching that bug anyway. Two possible workarounds in the meantime:-

      1. Listen for MOUSE_UP, by that time, index should be set.
      2. Implement a delay – yuk.

      PS: the other bugs you filed are really omissions, or differences between expectation and implementation. MouseEnabled is a tricky one within scrolling containers – because everything is mouse disabled, and mouse events are intercepted and re-transmitted. Why? – to determine whether the mouse (touch) event was indeed a touch/click, or if it was a scroll. So your bug report is actually a feature request – “Give me a way of disabling UI components”

      (PPS: Try background=”#f3f3f3,#f3f3f3,#f3f3f3″)

      • Richard Tolley / Jul 6 2011 3:28 pm

        1. The workaround works a treat – THANK YOU! – I can now get on with the code.
        2. Understood about the feature request – would be great if you could find the time.
        3. background=”#f3f3f3,#f3f3f3,#f3f3f3″ works a treat – THANK YOU!

        Thanks again for the really quick response.

        Rich

      • Richard Tolley / Jul 7 2011 1:13 am

        One thing for anyone browsing this – the work-around for clickableGroup MOUSE_UP leads to multiple events being dispatched – one per row in the clickableGroup – I have tested UIForm.CLICKED – it fires only once.

        @Daniel

        When you get a few free minutes could you tell me how to change the focus colour on an input? I’ve discovered that you can pass background=”#RGB1,#RGB2,#RGB3,#RGB4″ to set border and shadow options. I’m just a bit stuck trying to change a purple/blue highlight to white when you select the input.

        Regards

        Rich

      • Daniel Freeman / Jul 7 2011 1:41 pm

        Just uploaded MadComponentsLib0_5_4.swc. Take a look at the release notes. I think you’ll find that it solves most of your problems. 🙂

      • Richard Tolley / Jul 7 2011 2:44 pm

        can’t wait to try it – will be downloading in a few minutes. 🙂 THANK YOU!

        Quick question before I file a possible bug report.

        I’ve spent hours on this – I couldn’t reproduce it in any example I tried to write to send you 😦 – meaning it was an error in my code (and I’ve got a lot of it now)

        until….

        protected static const TODAY_LIST_SPOUSE_EDITOR:XML =
        <scrollVertical alignV="fill" alignH="fill" background="#C5CCD4,#CBD2D8,10,0" colour="#ABABAB" gapV="5">
        <label>Spouse Details</label>
        <group id="todayListSpouseEditorGroup">
        <columns widths="85,100%">
        <label id="tlpe_lblTitle" alignH="right">{LABEL_TEXT}title</label>
        <input id="tlpe_txtTitle" alignH="fill" background="#ababab,#ffffff,#ffffff,#ffffff"></input>
        </columns>
        <columns widths="85,100%">
        <label id="tlpe_lblFName" alignH="right">{LABEL_TEXT}first name</label>
        <input id="tlpe_txtFName" alignH="fill" background="#ababab,#ffffff,#ffffff,#ffffff"></input>
        </columns>
        <columns widths="85,100%">
        <label id="tlpe_lblLName" alignH="right">{LABEL_TEXT}last name</label>
        <input id="tlpe_txtLName" alignH="fill" background="#ababab,#ffffff,#ffffff,#ffffff"></input>
        </columns>
        </group>
        </scrollVertical>;

        ——————————————————

        var fname:UIInput = UIInput(UI.findViewById(“tlpe_txtFName”));
        fname.text = “Grrrrrrrrrrr!”;

        Should it matter WHERE I set the text of the input control?

        If I set it in the class constructor I have a read/write input box. Everything is good.

        If I set it from a function called from an event handler the input is read only.

        Regards

        Rich

      • Richard Tolley / Jul 7 2011 3:17 pm

        WOW – just checked out the changes – don’t know quite what to say – everything I hoped for and more.

        Rich

  7. Richard Tolley / Jul 14 2011 2:12 pm

    Hi Daniel

    I’m struggling with buttons at the moment.

    Two things I’m trying to do.

    Hi Daniel

    Couple of questions about buttons.

    <columns alignH="fill">
    <button>button one</button>
    <button>button two</button>
    <button>button three</button>
    </columns>

    1. Can you set the height of a button using XML? I’ve tried setting height=”100″ on the individual buttons, the columns tag. I’ve tried wrapping the columns in a vertical tag with height set to 100 and an alignV=”fill”.

    That’s the first question.

    2. Is it possible to set text so that you have 2 lines of text. i.e. in the example above I would like the word “button” on first line and “one” on second line. I’ve tried various combinations using a br tag to no avail.

    3. Finally a comment on 0.55 and the lines=”true” property

    When used with columns, would it be possible to extend it to

    lines=”true,false,true,true”

    Where you cycle through the columns indicating to display a vertical line or not.

    Best Regards

    Rich

    • Daniel Freeman / Jul 14 2011 5:54 pm

      Yes, this is something I need to change (Issues 1 and 2). In fact, when I wrote the button, I felt that I should have made it more like the native Android button. (so alignV=”fill” should do the same as android:layout_height=”fill_parent”). I’ll fix multiline labels too.

      It’s not a big fix, do you have anything else to put on the list, and make a new release more worthwhile?

      For now, the easiest fix is to utilise a button skin. An image of the button which includes the label.

      [button skin={getQualifiedClassName(SKIN)}/]

      Issue 3 is easy. Each child of the [horizontal], or [columns] has a line between. So if you don’t want a line between two things, wrap them up in a nested [horizontal] or [column], so they count as one thing.

      [columns widths=”30%,70%” lines=”true”]
      [slider/]
      [columns widths=”60%,40%”]
      [slider/]
      [slider/]
      [/columns]
      [slider/]
      [/columns] = four sliders, but only two lines.

      • Richard Tolley / Jul 14 2011 6:29 pm

        Thank you. Sounds good – I will implement.

        OK – since you asked – some more wish list items…

        I have a screen where I need to add and remove rows from a clickableGroup/group.

        So, in the style of iOS – the ability to easily add a row to a clickable group – complete with animation 🙂

        The ability for a row to dispatch a slide left event to allow me to display a delete button.

        an alpha fade for navigator bar and tab bar when you set the visible to true/false – think full screen video on iPhone – touch the screen and the top/bottom bars fade in and out.

        Also – I’m not sure if it’s my code (I can’t really see how it is) but AIR desktop – list component doesn’t appear to scroll. You can slide it down and see the bottom (elastic drag) but it doesn’t actually scroll. This doesn’t affect mobile operation.

        Finally – I’m having trouble when publishing to web. Again – I haven’t played around long enough really but I think you’re hard coding the width and height of the movie if you detect plugin/activeX as the player type (pure speculation here)

        It would be nice to be able to override this behaviour.

        The last thing that would be really nice is a global style that I could call to say – skin=”iOS”, skin=”Android”, skin=”Blackberry”

        I know you’ve given us the ability to skin our own components but you’ve done such a nice job on most of them….

        Regards

        Rich

  8. Richard Tolley / Jul 14 2011 6:35 pm

    One very last one …

    Text style for <input>

    I’m probably missing something somewhere but it would be nice if you could set text with a font tag.

    Radio Buttons – I don’t think I’ve ever seen them on an iPhone but what do you use if you need someone to chose between 3 or 4 options?

    Drop down list in the style of iOS.

    And at some point (I think you had one originally) a datagrid or table with clickable headers.

    Sorry – getting carried away.

    The two top-most on my wish list are the list scrolling on desktop and set text style for input.

    Best Regards

    Rich

    • Daniel Freeman / Jul 14 2011 8:26 pm

      That’s lot’s to think about. 🙂

      UI.create(); has optional parameters for width and height. So on AIR for desktop, you can do: UI.create(this, LAYOUT, stage.stageWidth, stage.stageHeight); This will solve the problem with the scrolling list too. (It happens because it thinks the displayable area is the area of the screen, not the window).

      Can you give me an example of an iPhone app that has a drop-down list? Can you use a pop-up window with a list? Or a sliding drawer? With a list inside. By the way, alignV=”no scroll” should prevent the list from moving.

      By the way, you can make a kind of table using a List and a custom renderer.

      [list]
      {DATA}
      [columns widths=”30%,30%,40%” lines=”true”/]
      etc.. etc…

      • Richard Tolley / Jul 15 2011 12:35 am

        Great info – thank you.

        Drop down list – I was thinking of Safari on the iPhone when visiting web pages with drop down lists. It effectively uses a picker as the drop down factory. I have no idea where to start with mobile development but for desktop development replacing the drop down factory is really simple.

        <mx:ComboBox id="cb" labelField="fname">
        <mx:dataProvider>
        <mx:Object fname="one" lname="1"/>
        <mx:Object fname="two" lname="2"/>
        <mx:Object fname="three" lname="3"/>
        <mx:Object fname="four" lname="4"/>
        <mx:Object fname="five" lname="5"/>
        </mx:dataProvider>
        <mx:dropdownFactory>
        <mx:Component>
        <mx:DataGrid showHeaders="false">
        <mx:columns>
        <mx:Array>
        <mx:DataGridColumn dataField="fname"/>
        <mx:DataGridColumn dataField="lname"/>
        </mx:Array>
        </mx:columns>
        </mx:DataGrid>
        </mx:Component>
        </mx:dropdownFactory>
        </mx:ComboBox>

        It’s NOT a major request – more of an … if it’s easy. I don’t actually have a use for it at the moment – just thought Safari was very slick in it’s approach.

        Thanks for the info

        UI.create(this, LAYOUT, stage.stageWidth, stage.stageHeight);

        In some ways this is perfect and will definitely get me out of a hole.

        I can see that I’m going to run into an issue though 😦 I’m going to have to have a fixed size AIR app. Width isn’t much of a problem – it’s the length (isn’t it always :$)

        Is there anyway you could let me set a parameter to say – take on the dimensions of the application rather than the capabilities.

        This would allow people to have an air app with MinWidth, MaxWidth, MinHeight and MaxHeight set and allow them within reason to size the app the way they want.

        This is probably now my number one feature request.

        I’m building an app that is primarily going to be used on netbooks (I know I’m mad going the mobile route) but with so many pads and phones out there I wanted a single app that would run on everything.

        I will hard code the dimensions for the time being. Interestingly it’s not perfect – bit of a glitch at the bottom and the list doesn’t render perfectly either but wrapping the list in a scrollVertical almost fixes the issue.

        As always

        Best Regards

        Rich

  9. NAGAI Katsunori / Jul 29 2011 12:42 am

    Thank you very much for your wonderful works!
    I have some questions about ImageLoader.

    I can’t catch complete event.

    imageLoader.loaderInfo.addEventListener(Event.COMPLETE, onLoaded);
    imageLoader.value = “http://www.mysite.jp/image.jpg”;

    function onLoaded(evt:Event):void
    {
    trace(“loaded”);
    }

    To catch the event, I think we need loaderInfo property?

    Please let me know how to catch ImageLoader complete event.

    And I would like to have mad compo API documentation.

    • Daniel Freeman / Jul 29 2011 8:13 am

      At the moment the documentation are the examples, and madCode0_5_5.pdf from the download site. When the API settles down a bit (and when I have time), I DO plan to write class documentation more in the style of Adobe livedocs.

      Apologies that this particular event isn’t documented.

      imageLoader.addEventListener(UIImageLoader.LOADED, onLoaded);

      It’s a bubbling Event.

      On error, you’ll receive SecurityErrorEvent.SECURITY_ERROR, IOErrorEvent.IO_ERROR, or ErrorEvent.ERROR direct from the UIImageLoader instance (not loaderInfo).

      In version 0.5.8, I’ve made slight changes:-

      An error with UIImageLoader will ALWAYS dispatch an ErrorEvent.ERROR event, regardless of the error type. (so SECURITY_ERROR, and IO_ERROR events sre not dispatched – ErrorEvent.ERROR is dispatched instead in these situations).

      There is a new uiImageLoader.error property, which will be either:-

      i. An instance of the Error class.
      ii. An instance of SecurityErrorEvent.
      iii. An instance of IOErrorEvent.

      • NAGAI Katsunori / Jul 30 2011 5:54 am

        Thank you very much for your quick reply.
        I could catch the event.

  10. Donny / Sep 3 2011 12:24 am

    Firstly, I want to congratulate you on MadComponents – it has certainly made my life easier for cross-platform development!

    I have a couple of questions though – ones that I cannot find answers for (might be a good idea to add the WordPress Search widget to your blog!).

    1. Is it possible to skin a UISwitch? In my application, I can’t see the “On” text when the switch is in the On position (it’s white on a white background for me).
    2. How do you set the font style on a button? It, too, is showing up as white text.

    I have been experimenting with applying the BlackBerry PlayBook skins to your Buttons, and it sort of works… the background color appears as it is defined in the BlackBerry skin, but the button press color does not. I’m using “qnx.ui.skins.buttons.RoundedButtonSkinWhite” for the button in case you can work out how to get the skin fully functioning 😉

    I can’t seem to find a skin property for the UISwitch to do the same thing though. Hmmmm…

    • Daniel Freeman / Sep 3 2011 8:37 am

      1. I’m getting ready to release the next update. Version 0.6. (Should be available on the code site tomorrow).

      I’ve made the UISwitch colours completely customisable in v0.6. You use the background property. background=”c0,c1,c2,c3,c4,c5″. However – there isn’t a skin option for UISwitch.

      c0 = on colour (same as colour property)
      c1 = off colour
      c2 = on text colour (if c3 not specified, off text colour too)
      c3 = off text colour
      c4 = button colour
      c5 = outline colour

      eg, background=”#FFFFFF,#FFFFFF,#666666″, would solve your white on white problem.

      2. <button><font color=”#666666″>press</font></button>

      In order to change the skin when pressed, you’d need to swap the skin in the UIButton.CLICK handler, and restore it (check for MouseEvent.MOUSE_UP on stage, and restore skin in handler for that.).

      • Donny / Sep 3 2011 9:09 am

        Cool!

        As for the second question – is there a way to set the font via pure actionscript? I’ve done that for the UIImage and UISegmentedControl (using XML) but it doesn’t appear to be available for the UIButton.

        Regarding the UISwitch – I think there is a small bug there. Setting the width works fine via the actionscript .width property, but reading that width property back always returns the same value – i.e. the width of the UISwitch prior to the update.

      • Daniel Freeman / Sep 3 2011 11:55 am

        button.text='<font size=”40″ color=”#FFCC66″>Hello</font>’;

        …should work

        The UISwitch isn’t supposed to change width. It’s a fixed size component.

  11. Donny / Jan 12 2012 9:17 am

    Hey Daniel,

    I’m attempting to skin the entire background of my app with a tiled image.

    Is there any way to do this via MadComponents?

    I assume it would need to be set inside <image></image>?

    • Daniel Freeman / Jan 12 2012 2:42 pm

      MadComponents doesn’t have that tiled background capability, but you can do it in ActionScript:-

      [Embed(source=”tile.png”)]
      protected static const TILE:Class;

      graphics.beginBitmapFill(new TILE().bitmapData);
      graphics.drawRect(0,0,stage.stageWidth,stage.stageHeight);

      If you want to tile a particular container, you could use UI.findViewById(), and apply the bitmapfill drawrect to that component.

      • Donny / Jan 13 2012 6:44 am

        Aha – more simple than I anticipated 🙂

        Thanks again for your infinite wisdom!

  12. Ramez / Jan 12 2012 9:47 pm

    Hi Daniel,

    I started playing with Mad Component and am banging my head against the wall for having wasted so much time with FlashBuilder! Thank you for making me feel stupid 🙂 It will take less than half the time to create the same app now 🙂

    Quick question: I’d like to create a window of a few rows of buttons (which open appropriate content). I’d like the buttons to wrap around automatically to the next row without me having to calculate how many buttons per row. This should greatly simplify layout, especially when rotating the device.

    Is this easily feasible or should I write my own AS functions to handle device rotate events and relayout the view?

    Interestingly enough, that seems to be the only issue I am facing and it’s still not v1.0 yet! Well done!

    Thanks in advance for your help.

    • Daniel Freeman / Jan 13 2012 6:08 am

      As you’ve realised, there is no wrap-around capability. I know HTML supports this. But Android XML Layout, and Android XML Layout don’t – and Madcomponents is more similar to these. Even making a form in Interface Builder or Xcode for iPhone requires you to handle orientation re-layout in code sometimes.

      So, how to get around it?

      If you put your buttons inside a <columns> container – this will ensure that they are regular sizes, and they automatically adapt to screen width. This is the easiest way – but columns doesn’t allow you to vary the number of buttons.

      <columns alignH=”fill”>
      <button …etc…

      I can think of two ways around this:-

      1. The first is to move the buttons around yourself in ActionScript as you suggest.

      2. The second is to make different page layouts for landscape and portrait, and in ActionScript, just change the page in response to orientation change:-

      <pages id=”orientation”>
      {PORTRAIT_LAYOUT}
      {LANDSCAPE_LAYOUT}
      </pages>

      I put a RESIZED event into MadComponents, so you can use this ensure that your orientation change code happens AFTER MadComponents does its own adjustments.

      UI.create(this, LAYOUT);
      addEventListener(UI.RESIZED, orientationChangeHandler);

      • Ramez / Jan 13 2012 9:27 pm

        Thanks!

        While doing this I am facing an interesting problem. Can I have a fixed height header and footer (custom using images and labels), but the content between them has variable height based on stage height? Specifically, if we rotate, the header and footer stay with the same height while the height of the content between them gets adjusted.

        I thought this would be easy to grasp. What I thought would be trivial is quickly becoming a challenge. I couldn’t find in the pdf docs the difference between [rows] and [vertical] – and [columns] and [horizontal], maybe that’s the secret to this problem.

        I’d be very grateful for your insight.

  13. Ramez / Jan 14 2012 5:28 pm

    Fixed issue above. This component, while powerful, really targets smartphones. So some work arounds are needed.

    For everyone’s benefit, here is how we created a complex layout:

    we separated the different elements (header, content, footer) into different UI’s using the class UIForm (which seems to be the basis of everything else). The class UI is actually static, so you can’t use it more than once.

    If there is a better way, please tell me 🙂

    • Daniel Freeman / Jan 15 2012 3:23 am

      Sorry about the delay.

      Yes, use UIForm to create multiple instances.

      protected var _layout:UIForm;

      if (_layout) { //Use this if you wish to clear the existing layout
      UI.clear(_layout);
      }

      _layout = new UIForm(this, xml, attributes);

      to find an id, use:-

      _layout.findViewById(“id”);

  14. Jon Tetzlaff / Feb 26 2012 10:58 pm

    When loading an image dynamically with is there a way to refresh the view? I don’t always know how big the image will be so I can’t hardcode a size. The picture ends up behind all of my other components. Is there a way to refresh the layout?

    • Daniel Freeman / Feb 27 2012 1:01 am

      Yes. autoLayout=”true” for the parent container.

      <vertical autoLayout=”true”>
      &ltimageloader etc…etc…

Trackbacks

  1. Tutorial 2: Images, and Nine Patch Images in MadComponents … | Flash | Adobe-Tutorial.com
  2. AS3 MadComponents Tutorial Series – Starting Out | Caffeine Industries

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: