Flash ListBox Alternative

Posted 5/12/2006 3:29 PM by sleekdigital | Categories: Flash

The ListBox Component that comes with Flash can be handy, but it has some shortcomings that limit its usefulness. For example, the scrolling logic causes items to reload each time they come into view. If you are loading external content, this causes a bothersome blinking effect.  Also the CellRenderer API is a little difficult to work with for some folks.  So, I put together some ActionsScript 2 classes that use the scrollpane component to build a scrolling list of items. It works similar to a ListBox component but with some additional functionality and without all these problems.

You can download the source from here.

Note that in the example fla, not all the items in the list have a caption under them.  This is not a bug, just an example to show that the captions were made optional.



It looks like a lot of code, but for general usage the only classes you need to pay much attention to are:
ScrollList - the main class that you instantiate
IListItem - the interface that you implement in order to create an item template.

Other important classes...

AssetListItem - is just a simple example implementation of IListItem so you can easily see how you might implement some of the methods.  In fact you might use the exact implementation for many of the methods.  The methods that will likely be specific to your implementation are:

setData - here is where you process the xml node that is passed into the item and use it to configure the display of the item.
isReady -  This is used in case the item loads external content. It should return false until the content is loaded. If there is no external content, it should just return true.
showSelectedState / showNormalState - these you might leave as they are but it depends on how you want to handle the display of the corresponding states of the items.
destroy - this one applies if you plan on needing to dynamically remove items from a list.  The example just deletes the movieclip, but if you are concerned about memory you might want to make sure everything is cleaned up before deleting the clip.


ListBase - you might also look at this class since ScrollList inherits from it.  There are a number of useful public methods in there.

Some Features...

  • It allows any scroll pane implementation to be used. You just have to write a simple adapter class. The zip file includes adapters for macromedia's scrollpane and MCOM's scroll pane.
  • The scroll wheel will work where supported.
  • Supports the ability to drag and drop items within the list to change the order. All you have to do is have your item implementation dispatch "itemDrag" and "itemDrop" events at the proper time, setting itself as the event target. The ListBase class takes care of the rest for you.
  • Supports adding and removing items on the fly.
  • Dispatches some events: itemSelected, itemAdded, layoutComplete. It would be easy to add other events if desired.
  • If you want to have items that dynamically change size ( for example the user clicks to expand an item for more detail or something like that), this is supported. You simply make your item dispatch a "itemChangeSize" event at the appropriate time. I've even had items expand into a nested lists. The nested list was a non scrolling list built on the ListBase class.
  • Supports most methods you see in collection API's.

I'm sorry that I don't have better documentation for this, but this is not an official open source release, just me responding to requests to see the code.  If there are any questions about how to use it or feedback on the code please let me know.  Perhaps someday I can make an official release.  I hope to soon post some examples of the functionality.

If anyone uses this I would appreciate an email describing your project or a comment on this blog post with a link to your project.

Comments:

Franto | 5/17/2006 2:23 AM

in ListBas.as there are
bet.utils.Drawing

and this class is missing in you zip :)


sleekdigital | 5/17/2006 9:54 AM

Thanks for catching that, I will get that up in a few minutes.


sleekdigital | 5/17/2006 10:08 AM

All fixed. Thanks again.


Derrick | 6/22/2006 8:44 PM

Hi sleekdigital,

How do we change the look of the scrollbar?


Derrick | 6/22/2006 8:46 PM

Also,

I wanted to use an external XML file.

In the scrollListExample.fla I changed:
myXml.parseXML(xmlData);

to:
myXml.parseXML("the.xml")
but that did not work.

I just took the string and placed it in an XML file named "the.xml"


sleekdigital | 6/22/2006 8:59 PM

Hi Derrick,

The scroll bar, by default is the built in Macromedia V2 component. Skinning that has nothing to do with this code, you can find information on that in the Flash help.

To use an external XML file, you would use the flash XML object to load the file (myXml.load("filename.xml")) and then in the xml objects onLoad event you would do the databinding steps...

myList.setDataSource(myXml);
myList.dataBind();

Note: the above is not necesarily the exact code you would use... you need to make sure things are referenced properly depending on your situation.


sleekdigital | 6/22/2006 9:02 PM

Oh, about scrollbar skinning... You can get a reference to the scrollpane that is used by the ScrollList instance like this...

myList.getScrollPaneRef();


darklow | 6/26/2006 6:40 AM

I have strange scrolling with roller bug. I can't scroll till the end. This bug is also in original example. Anyone experienced same problems and resolved it?
darklow[at]flash[dot]lv


sleekdigital | 6/26/2006 10:09 AM

I noticed this too. What's really strange is that, this only happens with the Macromedia scroll pane, and not the Metaliq MCom scroll pane. The code used to handle the srcoll wheel scrolling is very simple and straight forward. So at first glance, this bug makes little sense. I'll post an update when I learn more


sleekdigital | 6/26/2006 10:16 AM

Right after my response it dawned on me... The difference is probably in how the 2 components handle vposition values that are out of range. For example, as you scroll down, and get near the bottom, eventually you get to a vposition value that is further down than the content. The MCom scrollpane handles this by scrolling to the very bottom of the content. The MM scrollpane handels it by doing nothing. I'm not sure what the best way will be to fix this, but at least I'm pretty sure I understand why its happening.


woods | 7/4/2006 8:36 AM

Hello SleekDigital,

Your work is sleek indeed!

I am having trouble getting an external xml to work in the sample file (following the comment to Derrick), could you please show the xml load object in context to the rest of your code or possibly post a .fla that uses an external file.

Thanks.


sleekdigital | 7/4/2006 9:30 PM

Sure Woods,
In the context of the sample it would look like this...

function main()
{
var myXml:XML = new XML();
myXml.ignoreWhite = true;
myXml.load("myFile.xml");


var myList:ScrollList = new ScrollList("aList", _root, 1, "ScrollpaneContent", DerrickListItem, 0, 0, 180, 220, ScrollPaneMM);


myList.setSpacing(10);
myXml.onLoad = function(success:Boolean)
{
if (success) {
myList.setDataSource(this);
myList.dataBind();
}
}
}

main();
stop();


Brad | 10/9/2006 1:50 PM

SleekDigital, nice work.

I am tring to implement the ExternalInterface into AssetListItem.as and for some reason I can't get it to work.

I'm tring to use flash to parse external XML and send it to Javascript to parse on the XHTML page, getURL was limited to 255 charc and I came accross the ExternalInterface, but I can't seem to get it implemented.

Any suggestions?

Thanks again,
Brad


Steve | 10/9/2006 5:56 PM

I don't think there is anything specific in my code that would have any affect on the usage of External Interface. Does your External Interface code work outside of the context of the AssetListItem?


Brad | 10/18/2006 3:31 PM

Thanks, got it to work, had to render out to Version 8.

New question. I have loaded a XML file into the list, in the XML I have a node called 'cat' is can either be 'A' or 'B'. I want to have a button that when clicks it only displays the XML nodes that have a 'cat' defined as 'A' in the list and the same with 'B', once the user clicks the button for 'B' the 'A' nodes go away and you are only left with the 'B' nodes in the list.

Hope this is clear, any suggestion?

Thanks,
B


Steve | 10/18/2006 8:16 PM

I can think of a number of ways to approach that scenario. One approach would be to make the cat node a property of the list item (that can easily be done in your list item implementation). Then when the button is clicked, use the getLength and getItemAt methods to loop through all the items and check the cat property. If the cat value is not the one you want you remove it (use removeItemAt method). When you want to restore the list back to all items just call the setDataSource and databind methods again...

myList.setDataSource(myXml);
myList.dataBind();

Hope that helps


Brad | 10/20/2006 2:20 PM

Thanks, I'm just stuggling with a few things. My appologies, I'm not that great at scripting so I really appeciate the help.

I can't figure out how to get removeItemAt() when triggered from my button to delete an item within the list. So any layout or examples of how it would be scripted would be a great help.

Thanks a million,
B


Steve | 10/21/2006 10:57 AM

You just need to make sure you have a proper reference to the list itself and then call the removeItemAt() method and pass in the index of the item you want to delete. Something like...

myList.removeItemAt(5);

Where myList is a reference to your scroll list instance.

My guess is that you may be having trouble understanding how to properly reference your list in the context of your button code. I can't really help you with that without knowing the details of your flash movie. Best thing I can suggest is that you learn all you can about "scope".


Brad | 10/23/2006 10:13 AM

Thanks again, I understand the referance of the instance. I have not modified the zip file, so the files are still pretty much the same way they were zipped up. I am referancing the list through my btn like this:

testBtn.onRelease = function(){
myList.removeItemAt(1);
}

and it still dosn't work. Even if I unzip the files fresh and simply add a new button to the stage with the above code. Any ideas?

Thanks again for you patients and help.
B


Steve | 10/23/2006 1:59 PM

I tried the code just as you described and it worked fine for me. Do you have that code inside the "main" function?


Brad | 10/23/2006 3:07 PM

Not at first, but now I do and it works great.

I was thinking I didn't need it in the main function. Now I have to try and figure how to populate the list with my different 'cat' using the example you gave me before.

Thanks again for all your help, I really apperciate it.

B


Brad | 12/13/2006 4:26 PM

Sleek, I just can't seem to figure it out, I don't understand enough about how the classes talk to one another. Is there any way I can get you to kinda "spell-out" how to implement the suggestion you gave earlier. Sifting through the 'cat' node and displaying only the ones needed.

Thanks so much for you help.

B


SleekDigital | 12/14/2006 12:05 PM

Sure, hit me on IM sometime and we can talk through it...

AIM or yahoo : sleekdigital
MSN : [url="mailto:skrichten@comcast.net" target="_blank">skrichten@comcast.net


Brad | 12/18/2006 3:22 PM

Do you think we can touch base tomorrow?

Thanks Again,
B


Viklaas | 1/10/2007 11:52 AM

Hi

Could you elaborate more on "elaborate",maybe an example.

Thanks


Viklaas | 1/10/2007 11:54 AM

Mmm what happened there

More on "itemChangeSize"


SleekDigital | 1/10/2007 9:47 PM

Hi Viklass,

Basically the code is setup such that the list listens for an event by the name of "itemChangeSize" on all of its items. When the event is encountered the list will automatically adjust ... it will redo the layout of all the items and reset the scrollbars etc...

So if at any time you want to have an item change size, all you have to do once you change the ites size is have your item dispatch that event and the list will adjust to the new item height by itself.

The code for dispatching the event would look something like this ...

dispatchEvent({type:"itemChangeSize", target:this, scrollTo:true});

Notice the "scrollTo" property in the event object. If you set that to true, the list will automatically scroll to the item that was expanded.

If you look at http://www.bet.com/onblast/ you can see all this in action. When you click on the down arrow in the bottom right of any of the items, it will expand the item to show a sublist. I did that by telling the item to display its sublist when the arrow is clicked and then dispatch the "itemChangeSize" event.


Viklas | 1/12/2007 6:55 AM

Thanks,you're a gentleman and a sailor.


Viklas | 1/12/2007 6:58 AM

Sorry,I'm new to this.One more question.In the xml you specify a url or movieclip.I load movieclips.I had to changed "loadMovieClip" to "attachMovie" How would I go about dispathing that event from my movieclip.Not from AssetListItem.


SleekDigital | 1/12/2007 3:01 PM

I'm not exactly clear on what you are asking. But in any case the List is only listenening to the list items, so ultimately the event must be dispatched from the list item.

If you want you can email me the list itme code you are working on and more details about what you are trying to accomplish. Just use the contact link in my site's main navigation.


Steph | 3/12/2007 2:37 PM

Hi, i need to implement this in a JAVA project, can i deploy the class with the rest of my class. if yes, how i call the flash class?

Thanks ---Steph


SleekDigital | 3/12/2007 8:46 PM

I'm sorry Steph, I'm not sure exactly what you are asking. If you like, feel free to email me with a more detailed explaination. Use the contact link on the main menu of my site.


gerond | 6/1/2007 10:47 PM

How to set vertical postion??


SleekDigital | 6/2/2007 7:41 AM

Gerond, Can you be more specific about what it is you want to do?


Evan | 6/18/2007 7:12 PM

This looks very useful Sleek.

I'll be using this in a prototype that displays dynamic long and short strings in a multi-column list. The long strings need to wrap and use additional lines as needed.

I need to feed the data to the list from actionscript though.
Do you have any code that uses your control without the external XML? And/or any suggestions for how to use addItem and replaceItemAt with your code?

Thanks,
-Evan


SleekDigital | 6/19/2007 10:33 AM

Hi Evan,

The example in the zip file doesn't use an external file, it just makes an XML object from a string. You could just use addItem to populate the list, but since it takes an XML node as the argument, its genreally easier to just pass a whole XML object to the setDataSource method. addItem can still be useful when you want to add items on the fly. Just make an XML node with the structure that your list item requires and pass it as the addItem method's parameter.

removeItemAt is probably used more often than removeItem, because with removeItemAt you can just pass in the index of the item to remove, while with removeItem you need to pass in a reference to the list item itself.

Hope that helps, if you have more questions feel free to use the contact link to send me an email, or use the Plugoo chat box


Mani | 6/26/2007 7:28 PM

Hello SleekDigital,

I really appreciate what you've done here. I've been needing a list component that can load all data at once and display horizontally or vertically. This seems to be the one, and it's put together rather nicely. Thanks for your great work.

There are still a couple things I'd like to do. First, I already have my XML data loaded into my model classes, and parsed as AS objects. I don't want to convert this data back to XML, so I want to load the list with an Array (ie: from a DataSet) instead. Second, I want to scroll the contents on hover as well as via the scrollbar.

For my first need, I'm looking at changing a couple of type declarations in your code. Namely: IList.addItem(itemData:Object), IListItem.setData(itemData:Object) and ListBase.addItem(itemData:Object). I'm extending ListBase and IListItem to suit my other particular needs (scrolling on hover, ect..), but I could not work around this particular need via simple class extension.. I don't want to fork off this (quasi) project (cause I'd like to submit my extensions later), but I would love some more flexibility here. (I've also taken liberty of adding a "sleekdigital" namespace to your classes. ) If you're into these changes, I'd be happy to submit my code for your consideration.

So basically, I love your work, and I would love to work with you to take it further. If not, then at least I'd like your blessings to take it in my own direction.

Thanks for your time and great work,
Mani
(workplay at soundsculpting dot org)


SleekDigital | 6/26/2007 8:22 PM

Thanks for the kind words, Mani. Great minds think alike, I've thought about exactly those same enhancements for this component. I'd be happy to look at your code and consider merging it with mine.

I originally did have namespaces assigned to these classes, but I took them out because it confuses some developers that are new to AS 2.

It sounds like you are on the right track for the additions you mention. For the "scroll on hover" feature, I would think that would best be handled by extending the ScrollList class. But then again, its been quite some time sice I have looked at the code :)


Brenden | 9/12/2007 11:59 AM

Hi Sleek,

Just had a good look at your work and it looks great! I was just wondering how would you convert it to add multiple items on each row so you have say 3 columns instead of one?

Cheers,

Brendz


SleekDigital | 9/13/2007 8:09 AM

That might be a little beyond what this component is suited for. There are some good Datagrid components out there that would work better for that situation. However, You can make a psudo-datagrid with this component simply by designing your list item to look like it has 3 columns. That would be very easy in fact. At least one person who contacted me is using it that way. But some datagrid functionality would be difficult to replicate.


SleekDigital | 9/13/2007 8:14 AM

Just an FYI ... Mani has made the enhancements that he mentioned in his previous post. We talked about making an official release on Google code or something like that in the near future.


Wie | 9/25/2007 3:26 AM

Just to make sure....
does this listbox support png icon? I have try it, but this listbox only support jpg icon.


Wie | 9/25/2007 5:02 AM

btw, can we put item in the listbox with icon in the left of the label? which part of actionScript should I change? can somebody help me? thx


SleekDigital | 9/26/2007 1:00 AM

This list will work with any image that works in flash. As far as layout, that's easy... the list uses a movieclip as a template for the list items. You can position things in your item template however you choose. You can also handle layout functionality in your IListItem implementation


Thomas | 11/21/2007 9:41 AM

How do I change the onRollOver-frame color on the thumbnails?


SleekDigital | 11/21/2007 10:34 AM

In the FLA there is a button symbol named "ItemBtn". You can set the mouse states there.


kennet | 1/4/2008 8:44 AM

i need to attach movieclip dinamically created how can i do this using your code. I need to avoid blinking on load new movieclip and reshing scollpane
thanks


erwin | 1/7/2008 10:10 PM

Is there a help for newbie here? I found this stuff very cool and tried to use it as a guide in my project. I just have one question about the function in AssetListItem.as:

public function init(x:Number, y:Number):Void
{
mx.events.EventDispatcher.initialize(this);
setPosition(x,y);
var me:AssetListItem = this;
theBtn.onPress = function()
{
me.dispatchEvent({type:"selected", target:me});
}
}

<<<< and I think this is the action when the icon/photo is clicked, Is it possible for that action to do loadMovie() or loadMovieNum() and carries the variable caption to the loaded movie?

I tried to do loadMovieNum('details.php', 1, 'post') and it works but when I use loadMovieNum('details.php?caption='+textTB.text, 1, 'post') it didnt work. Please help.

Thanks


SleekDigital | 1/30/2008 12:25 AM

Sorry for the delayed response erwin. I hope you check back and get this message. What I would do is listen for the "selected" event that is being dispatched there. then you can do whatever you want from there. But instead of trying to get the caption inside the loaded movie, why not just have the parent movie have a field to display the caption?


dvine | 2/28/2008 4:54 AM

Hey - nice work sleek!!

I do have one question though (or better two questions that are linked to each other)

Could you give an example on how to reorder items via dragging?
And the other thing thats probably linked to this - is it possible to drag items from one list to another if you have 2 lists on your screen??

And finally: is it possible to use MovieClips as items in the listbox???

Thank you in advance!
Daniel Weingarten


SleekDigital | 2/28/2008 1:00 PM

Drag and drop reordering is made very simple...

When you initialize your item renderer, setup handlers for onPress and onRelease of whatever part of your item that you want to initiate the drag/drop. In this example I set it up (using mx.utils.Delegate) on a movieclip inside my item renderer called "bg"

bg.onPress = Delegate.create(this, bgOnPress);
bg.onRelease = Delegate.create(this, bgOnRelease);

You could probably just use this.onPress etc... but then you can't easily listen for any other mouse events in your item renderer.

Then in your handlers you just dispatch the events mentioned in my post...

private function bgOnPress():Void
{
dispatchEvent({type:"itemDrag", target:this});
}
private function bgOnRelease():Void
{
dispatchEvent({type:"itemDrop", target:this});
}

That's all you need to do.


SleekDigital | 2/28/2008 1:05 PM

Your other questions. Dragging to other lists is not an included feature, but should be do-able with a little work.

Movieclips are already used as the item renderers. You create a class that implements the IListItem interface, attach that class to your movieclip and that movieclip is used as the item renderer, as long as you specific that class when you instantiate your list


erwin | 3/6/2008 7:44 AM

Hi SleekDigital, its me again. My last query was resolve by editing portions in the AssetListItem.as. I have another question since I tried to implement your script in this sample

http://erwinpangit.awardspace.com/ivomsgr/main.swf

what I'm trying to do here is to resize the scrollpane with respect to my value width and height and should stay its x,y position to where i set from _root.posX and _root.posY so that everytime I resize the window, the position must be the same. My question is how can I lock its x and y position? In ScrollList.as there's a function setPosition and I tried to set the values to 0,0. but still everytime I resize the window... It changes its location, Can you help me out how to lock its x,y position?

thanks.

erwin


erwin | 3/6/2008 8:04 AM

if the above link is not working, please user this link instead :
http://erwinpangit.no-ip.org/ivomsgr/main.html

regards.

erwin


SleekDigital | 3/9/2008 10:59 AM

Erwin, I'm not sure I completely follow your question, but it sounds more like a general flash question as opposed to something specific to the list code. The list will behave just like any other flash component in terms of positioning.


B. Smith | 3/27/2008 4:29 PM

Anyone have any examples of this useing Flash MX 2004? The included example doesn't load.


mmb | 4/9/2008 3:06 AM

hi
how can i access in root of flash to the values of propertis that are in the AssetListItem class


Sleekdigital | 4/10/2008 1:47 PM

mmb,
One way is to use the lists's getItemAt() method. Pass it the index of the item you want and it will return a reference to the item, and then of course you can access the properties. if its the selected item you want, there is of course the getSelectedItem method to get a reference to the selected item.


wintu | 6/24/2008 11:34 AM

hi sleek sir good tutorial

suppose when i rollover any image only text should be shown and all the images should be not visible

Post your comments:

Anti-spam Key
Please Type in the letters shown above (this helps prevent spam):

Name:

URL (Optional):


Your Comments:

Search



www This site

Blog Topics

Skip Navigation Links.