Scrolling a Flex List control horizontally

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 thoughts on “Scrolling a Flex List control horizontally

  1. 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.

  2. 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

    […]

    […]

  3. 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

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

  5. 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.

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

    Thanks in advance.

    1. 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

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

    1. 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

    1. 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

  8. 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

    1. 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

  9. 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

  10. 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

  11. 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);

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

  13. item is a subclass of button.

    item.addEventListener(MouseEvent.CLICK,handleClick);

    where handleClick is a event handler method

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

    Thanks for your time.

  15. 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.

    1. 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

Comments are closed.