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.

 
About The Author

Peter deHaan

Peter deHaan currently works for Adobe on the Flex SDK QA team. While not working on Flex, Flash, and ColdFusion applications, Peter enjoys making up bios and writing in 3rd person. Peter's rarely updated blog can be found at blogs.adobe.com/pdehaan/, actionscriptexamples.com, airexamples.com, and coldfusionexamples.com.

29 Responses to Scrolling a Flex List control horizontally

  1. s'ergo says:

    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. burn says:

    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. burn says:

    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. Vitalik says:

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

  5. goodness says:

    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. Veena Pandit says:

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

    Thanks in advance.

    • Peter deHaan says:

      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. Veena Pandit says:

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

    • Peter deHaan says:

      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

  8. Veena Pandit says:

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

    • Peter deHaan says:

      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

  9. Veena Pandit says:

    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

    • Peter deHaan says:

      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

  10. Veena Pandit says:

    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

  11. Veena Pandit says:

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

  12. Veena Pandit says:

    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

  13. Veena Pandit says:

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

  14. Veena Pandit says:

    Hmmm….Not sure how to post the code.

  15. Veena Pandit says:

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

  16. Veena Pandit says:

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

  17. Veena Pandit says:

    item is a subclass of button.

    item.addEventListener(MouseEvent.CLICK,handleClick);

    where handleClick is a event handler method

  18. Veena Pandit says:

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

    Thanks for your time.

  19. veena pandit says:

    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.

Leave a Reply

Your email address will not be published.

You may 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