Scrolling a Flex List control horizontally

by Peter deHaan on January 26, 2008

in List

The following example shows you how you can create a horizontally scrolling List control in Flex by setting the horizontalScrollPolicy property.

Full code after the jump.

View MXML

<?xml version="1.0" encoding="utf-8"?>
<!-- http://blog.flexexamples.com/2008/01/26/scrolling-a-flex-list-control-horizontally/ -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
        layout="vertical"
        verticalAlign="middle"
        backgroundColor="white">

    <mx:XML id="xmlDP">
        <root>
            <node>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</node>
            <node>Donec sit amet dui nec pede aliquam auctor.</node>
            <node>Integer vestibulum sodales dui.</node>
            <node>Sed nonummy ligula et tortor.</node>
            <node>Aenean varius neque vel felis.</node>
            <node>Phasellus venenatis ipsum sit amet nisi.</node>
            <node>Nullam vitae turpis et ipsum cursus venenatis.</node>
            <node>Pellentesque tincidunt pede non arcu.</node>
            <node>Aliquam ut massa quis ante dignissim egestas.</node>
            <node>Curabitur facilisis velit sit amet metus.</node>
            <node>Vivamus ornare massa ac massa.</node>
            <node>Nam accumsan rutrum purus.</node>
        </root>
    </mx:XML>

    <mx:List id="list"
            dataProvider="{xmlDP.node}"
            horizontalScrollPolicy="on"
            verticalScrollPolicy="auto"
            rowCount="6"
            width="200" />

</mx:Application>

View source is enabled in the following example.

Great taste! Less filling!
But there is one “gotcha”. If your List control is small (say, 100 pixels wide) and your text is long (say, 400 pixels wide), the List may not scroll all the way to the end of the text. The solution? Set the maxHorizontalScrollPosition property. (Thanks to Ella for the tip!)

Consider the following example. In this example we have two List controls. The List control on the left sets its width to 150 pixels, whereas the List control on the right sets its width to 150 pixels and uses the creationComplete event to call a function which sets the maxHorizontalScrollPosition property to the value of the list’s columnWidth property.

View MXML

<?xml version="1.0" encoding="utf-8"?>
<!-- http://blog.flexexamples.com/2008/01/26/scrolling-a-flex-list-control-horizontally/ -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
        layout="horizontal"
        verticalAlign="middle"
        backgroundColor="white">

    <mx:Script>
        <![CDATA[
            private function init():void {
                list2.maxHorizontalScrollPosition = list2.columnWidth;
            }
        ]]>
    </mx:Script>

    <mx:XML id="xmlDP">
        <root>
            <node>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</node>
            <node>Donec sit amet dui nec pede aliquam auctor.</node>
            <node>Integer vestibulum sodales dui.</node>
            <node>Sed nonummy ligula et tortor.</node>
            <node>Aenean varius neque vel felis.</node>
            <node>Phasellus venenatis ipsum sit amet nisi.</node>
            <node>Nullam vitae turpis et ipsum cursus venenatis.</node>
            <node>Pellentesque tincidunt pede non arcu.</node>
            <node>Aliquam ut massa quis ante dignissim egestas.</node>
            <node>Curabitur facilisis velit sit amet metus.</node>
            <node>Vivamus ornare massa ac massa.</node>
            <node>Nam accumsan rutrum purus.</node>
        </root>
    </mx:XML>

    <mx:List id="list1"
            dataProvider="{xmlDP.node}"
            horizontalScrollPolicy="on"
            verticalScrollPolicy="on"
            rowCount="6"
            width="150" />

    <mx:List id="list2"
            dataProvider="{xmlDP.node}"
            horizontalScrollPolicy="on"
            verticalScrollPolicy="on"
            rowCount="6"
            width="150"
            creationComplete="init();" />

</mx:Application>

View source is enabled in the following example.

While this technique of setting the maxHorizontalScrollPosition property to the columnWidth property seems to work in this instance, I’ve only done very limited testing. I haven’t tested in all cases such as if you load strings from external files or web services, or if your List has long strings which aren’t currently visible in the list’s view. You may have to do some tweaking to get this working in your particular circumstance.

{ 29 comments… read them below or add one }

1 s'ergo March 12, 2008 at 9:37 am

very nice trick.
i have another question about TileList and scrolling (actually two):
- how can i control amount of scrolling pixels, say vertical? by default scroll occurs for one line (i.e. scroll for one item along), but what i should to do if i want to scroll for three line?
- how can i use liveScrolling properties in TileList? simply set its to true change nothing…
anyway thank you, do a big deal.

Reply

2 burn May 19, 2008 at 3:48 am

Hi there,

I had a similar problem in an app of mine in which a list’s data provider is being received from an http service. For some strange reason the list did show all received data but without adapting the required maxHorizontalScrollPosition. so what worked fine for me was listening to the dataprovider’s collectionChange event and setting the list’s maxHorizontalScrollPosition according to the measured list width.

cheers, burn

[...]

[...]

Reply

3 burn May 19, 2008 at 3:51 am

ok, my example code got cut away. but the magic happens when you calculate the required horizontal width with measureWidthOfItems(0,0) and assign the measured value minus the lists’s width to your list’s maxHorizontalScrollPosition.

burn

Reply

4 Vitalik February 23, 2009 at 8:12 am

i have a problem in scrolling for all application … it’s dont show all region of application it cut from top and left

Reply

5 goodness May 11, 2009 at 12:56 pm

Follow up on burn’s post. Setting the maxHorizontalScrollPosition to the list’s column width actually tells the list that it can scroll a full list-width beyond where it should be allowed to (at least in the latest flash). That’s why you need to subtract out the list’s width from the max width.

Reply

6 Veena Pandit July 23, 2009 at 4:36 pm

How do I position (dock) the horizontal scroll list component to the bottom of the web page like a task bar?

Thanks in advance.

Reply

7 Peter deHaan July 23, 2009 at 5:34 pm

Veena Pandit,

If you are using an absolute layout, just set the bottom property to 0.
If you are using a vertical layout, i’d just create a <VBox/> and set it’s height to 100% and then add the horizontal scroll list below that. Then add all your content to the VBox instead of the Application directly.

Peter

Reply

8 Veena Pandit July 24, 2009 at 1:06 pm

I am trying to populate the list with a horizontalScrollList.addChild(item) dynamically. Nothing is getting added to the list.

Reply

9 Peter deHaan July 25, 2009 at 10:10 am

Veena Pandit,

You would add you item to the dataProvider itself, not use the addChild() method:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
        layout="vertical"
        verticalAlign="middle"
        backgroundColor="white">
 
    <mx:Script>
        <![CDATA[
            protected function btn_click(evt:MouseEvent):void {
                var value:String = new Date().toString();
                horizontalScrollList.dataProvider.addItem({label:value});
            }
        ]]>
    </mx:Script>
 
    <mx:Button id="btn"
            label="add item to horizontal list"
            click="btn_click(event);" />
 
    <mx:HorizontalList id="horizontalScrollList"
            labelField="label"
            itemRenderer="mx.controls.Text"
            horizontalScrollPolicy="on"
            width="100%"
            columnWidth="80"
            height="100"
            rowCount="1">
        <mx:dataProvider>
            <mx:ArrayCollection />
        </mx:dataProvider>
    </mx:HorizontalList>
 
</mx:Application>

Peter

Reply

10 Veena Pandit July 25, 2009 at 12:03 pm

Thanks!
How do I add eventListeners to the individual items in the horizontalList?

Reply

11 Peter deHaan July 25, 2009 at 3:57 pm

Veena Pandit,

It depends on what you’re trying to do, but typically you’d listen for the change event on the HorizontalList control and handle your code there. For example, the following code shows how you can determine when the user has selected a new item in the HorizontalList control and the show an Alert dialog:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
        layout="vertical"
        verticalAlign="middle"
        backgroundColor="white">
 
    <mx:Script>
        <![CDATA[
            import mx.events.ListEvent;
            import mx.controls.Alert;
 
            protected function horizontalScrollList_change(evt:ListEvent):void {
                var selectedLabel:String = horizontalScrollList.itemToLabel(horizontalScrollList.selectedItem);
                Alert.show(selectedLabel, "You selected:");
            }
        ]]>
    </mx:Script>
 
    <mx:HorizontalList id="horizontalScrollList"
            labelField="label"
            columnWidth="120"
            columnCount="5"
            height="100"
            rowCount="1"
            change="horizontalScrollList_change(event);"
            verticalAlign="middle">
        <mx:dataProvider>
            <mx:ArrayCollection>
                <mx:Object label="Flex 3" />
                <mx:Object label="Flex Builder 3" />
                <mx:Object label="Flash CS4" />
                <mx:Object label="ColdFusion 8" />
                <mx:Object label="Fireworks CS4" />
                <mx:Object label="Dreamweaver CS4" />
                <mx:Object label="Photoshop CS4" />
            </mx:ArrayCollection>
        </mx:dataProvider>
    </mx:HorizontalList>
 
</mx:Application>

Peter

Reply

12 Veena Pandit July 25, 2009 at 4:44 pm

I added an event listener to each button before I added it to the horizontalScrollList. I have an event listener so:

handleButtonClick(event:MouseEvent):void {)

how do I change the code above so that, I call the eventListener handleButtonClick when a button is clicked in the horizontalScrollList.

Thanks,

Veena

Reply

13 Peter deHaan July 25, 2009 at 11:56 pm

Veena Pandit,

I’d probably do something like the following, or create a custom item renderer:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
        layout="vertical"
        verticalAlign="middle"
        backgroundColor="white">
 
    <mx:Script>
        <![CDATA[
            import mx.events.ListEvent;
            import mx.controls.Alert;
 
            protected function horizontalScrollList_change(evt:ListEvent):void {
                var itemData:Object = evt.itemRenderer.data;
                this[itemData.clickFunc].call(null, itemData);
            }
 
            private function flexBtn(evt:Object):void {
                Alert.show("You clicked the Flex button.", evt.label);
            }
 
            private function flexBldBtn(evt:Object):void {
                Alert.show("You clicked the Flex Builder button.", evt.label);
            }
 
            private function flashBtn(evt:Object):void {
                Alert.show("You clicked the Flash Authoring button.", evt.label);
            }
        ]]>
    </mx:Script>
 
    <mx:HorizontalList id="horizontalScrollList"
            itemRenderer="mx.controls.Button"
            backgroundAlpha="0.0"
            borderSides=""
            useRollOver="false"
            columnWidth="120"
            columnCount="5"
            height="100"
            rowCount="1"
            change="horizontalScrollList_change(event);"
            verticalAlign="middle">
        <mx:dataProvider>
            <mx:ArrayCollection>
                <mx:Object label="Flex 3" clickFunc="flexBtn" />
                <mx:Object label="Flex Builder 3" clickFunc="flexBldBtn" />
                <mx:Object label="Flash CS4" clickFunc="flashBtn" />
            </mx:ArrayCollection>
        </mx:dataProvider>
    </mx:HorizontalList>
 
</mx:Application>

Peter

Reply

14 Peter deHaan July 25, 2009 at 11:57 pm

For lots of excellent examples on custom item renderers, see Alex Harui’s blog at http://blogs.adobe.com/aharui/item_renderers/.

Peter

15 Veena Pandit July 26, 2009 at 5:53 am

Hi Peter,

There isn’t one about HorizontalLists in there though. I just need to know how to propagate the event from the container(HorizontalList, the ListEvent) to the individual Object that was clicked on(the button in the list,the MouseClick Event).

Thanks,

Veena

Reply

16 Veena Pandit July 26, 2009 at 7:16 am

Sorry did not see the earlier post. I am trying it out now

Reply

17 Veena Pandit July 26, 2009 at 8:37 am

Peter,

I like your example above, except that I am adding objects to the horizontalList at runtime.
and my dataProvider is defined so in the HorizontalList:

So I dont know how to hook to the original event listener in the object in the horizontalList.

Thanks in advance,

Veena

Reply

18 Veena Pandit July 26, 2009 at 8:41 am

Sorry I did not see the note below:
Let me try again:

Reply

19 Veena Pandit July 26, 2009 at 8:42 am

Hmmm….Not sure how to post the code.

Reply

20 Peter deHaan July 26, 2009 at 1:25 pm

Veena Pandit,

You need to escape the < tags as &lt; and the > tags as &gt;.

Peter

Reply

21 Veena Pandit July 26, 2009 at 4:58 pm

My dataProvider is defined like this:

<mx:dataProvider>
    <mx:ArrayCollection/>
</mx:dataProvider>

My objects are populated at runtime. So from the example above

<mx:dataProvider>
    <mx:ArrayCollection>
        <mx:Object label="Flex 3" clickFunc="flexBtn" />
        <mx:Object label="Flex Builder 3" clickFunc="flexBldBtn" />
        <mx:Object label="Flash CS4" clickFunc="flashBtn" />
    </mx:ArrayCollection>
</mx:dataProvider>

I cannot use the clickFunc

Also my event listener has a parameter that is of type MouseEvent.Click not of type Object.

(I added the semicolons; too bad you can’t delete a post);

Reply

22 Peter deHaan July 26, 2009 at 5:02 pm

How are you populating the items in the data provider at runtime?

Peter

Reply

23 Veena Pandit July 27, 2009 at 4:48 am

taskBar.dataProvider = new ArrayCollection(); in the init method
taskBar.dataProvider.addItem(item); at runtime.

Reply

24 Peter deHaan July 27, 2009 at 7:11 am

And what is an “item”? How are you attaching your listeners to it?

Peter

Reply

25 Veena Pandit July 27, 2009 at 9:23 am

item is a subclass of button.

item.addEventListener(MouseEvent.CLICK,handleClick);

where handleClick is a event handler method

Reply

26 Veena Pandit July 27, 2009 at 12:40 pm

Could you also post a small example on how to add objects to the horizontalList dynamically?

Thanks for your time.

Reply

27 Peter deHaan July 28, 2009 at 7:05 am

Veena,

My example above shows how you can add items to the HorizontalList data provider dynamically using ActionScript:
http://blog.flexexamples.com/2008/01/26/scrolling-a-flex-list-control-horizontally/#comment-4725

Peter

Reply

28 veena pandit July 28, 2009 at 7:29 am

Cool! Given this example, how do I capture the MouseEvent(MouseEvent.CLICK) when an individual item in the
list is clicked. I have seen the clickFunc for when you add items in a static fashion.

Reply

29 Peter deHaan July 28, 2009 at 8:10 am

Veena,

My earlier example shows how you can listen for changes in the selected item on a HorizontalList control by using the change event: http://blog.flexexamples.com/2008/01/26/scrolling-a-flex-list-control-horizontally/#comment-4730

Or, you could use the earlier solution of using some clickFunc type approach which calls different methods depending on which specific item was clicked.

Or, you could look at creating a custom item renderer which may do what you want.

Peter

Reply

Leave a Comment

Sorry, this blog is terrible at eating HTML comments.
If you're pasting any HTML/XML/MXML code, you need to convert your < characters to &lt; and your > characters to &gt; .

You can use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="">

Anti-Spam Protection by WP-SpamFree

Previous post:

Next post: