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);
How would I push data to a DividedList to different groups?
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.
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
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;
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.
Thanks man. Super awesome work by the way. You have saved me tons of time and with a really slick interface.
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.
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,
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.
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,
@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]
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.
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.
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?
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)
how would that work in a list row that is being populated by pushing to an array?
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.
How do you change the color of the navigation arrows? For example the rightArrow and leftArrow.
var treeNavigation:UITreeNavigation = UITreeNavigation(UI.findViewById(“myNavigation”));
treeNavigation.navigationBar.backButton.colour = 0xCCCCCC;
treeNavigation.navigationBar.rightArrow.colour = 0xCCCCCC;
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?
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”/]
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,
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.
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.
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;
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?
@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.
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?
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.
Awesome! That just made my weekend. Thanks for all your help! I’m sure I’ll be back for more…
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.
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?
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)
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!
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.
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.
Check out version 0.4.3 for fixes to the issues raised here.
Does that count my issues with the scrolling?
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.
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 🙂
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.
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
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.
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!
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.
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)
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]
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.
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.
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.
Depends on when the next update is scheduled. I can wait for a week to 10 days on this.
It’s in version 0.4.5 available now.
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.
… 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?
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;
}
}
}
Is there away we can programmatically scroll a list to a certain index?
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.
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;
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.
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.
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?
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)
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…
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.
Fixed in 0.4.9. Thanks for finding these bugs.
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.
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.
Just logged another bug:
:ReferenceError on UINavigation.goToPage() when clicking first group only”
Might be related to the bug 6 you just fixed.
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.
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.
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.
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);
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.
Is there a way to have different height values for different rows in a list?
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).
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.
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.
I will give it a try. Thanks for the info.
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?
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.
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
wre is the download link for version 0.4.5?
If you go to the download page, http://code.google.com/p/mad-components/downloads/list
, you can change the search option to “All downloads”, and click the search button. Then you’ll see a list of all previous deprecated downloads.
But the latest version, 0.5 is recommended.
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.
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..)
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));
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
I’ve updated this example:-
http://code.google.com/p/mad-components/source/browse/trunk/MadComponentStuff/src/MadComponentsPureList.as
… that’ll show you how it’s done.
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.)
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>;
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.
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);
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));
I’ve made you an example at:
http://code.google.com/p/mad-components/source/browse/trunk/MadComponentStuff/src/MadComponentsPureSegmented.as
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 =
I’m afraid wordpress strips out xml tags. Try again with [ and ] instead of lt and gt.
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…
I’ve made another helper class. For UIScrollVertical
http://code.google.com/p/mad-components/source/browse/trunk/PureMadComponents/src/pureHelpers/UIScrollVerticalMaker.as
Here’s an example making a scrolling form:-
http://code.google.com/p/mad-components/source/browse/trunk/PureMadComponents/src/MadComponentsPureScrollVertical.as
Slick as a whistle. Thanks for the quick and helpful feedback.
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 ?
Do you mean that the background (around the button) intercepts mouseevents? Probably best if we discuss this on the Facebook page.
https://www.facebook.com/groups/madcomponents/