Flex ListEx component 


ListEx component is extension of List component with code to handle horizontalScrollBarPolicy ="auto" 


<?xml version="1.0" encoding="utf-8"?>
<mx:List xmlns="*" xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
    <![CDATA[
        import mx.core.EventPriority;
        import mx.events.ScrollEvent;
        import mx.core.ScrollPolicy;
        import mx.core.mx_internal;
        import mx.events.CollectionEvent;
        import mx.events.CollectionEventKind;
       
        private var originalPolicy:String;
       
        /**
         * @private
         */
        private var _horizontalScrollForVisibleItems:Boolean = false;
       
        /**
         * Computing width of all the items in the dataProvider can cause performance
         * problems if the number of items is very high. To compute the width of all the
         * items all the items need to be fetched to the client if the data is remote.
         * In these cases horizontalScrollForVisibleItems can be set to true so that
         * maxHorizontalScrollPosition is computed only for the items visible in the List.
         */
        public function get horizontalScrollForVisibleItems():Boolean
        {
            return _horizontalScrollForVisibleItems;
        }
       
        /**
         * @private
         */
        public function set horizontalScrollForVisibleItems(v:Boolean):void
        {
            _horizontalScrollForVisibleItems = v;
        }

        /**
         *  Save the user setting for our future reference
         */
        override public function set horizontalScrollPolicy(val:String):void
        {
            super.horizontalScrollPolicy = val;
            originalPolicy = val;
            if (val == ScrollPolicy.AUTO && horizontalScrollForVisibleItems)
                addEventListener(ScrollEvent.SCROLL, vScrollHandler, false, EventPriority.DEFAULT-2);
            else
                removeEventListener(ScrollEvent.SCROLL, vScrollHandler);
        }
       
        /**
         *  Measure the required width by measuring the items and set horizontalScrollPolicy
         *  accordingly.
         *  makeRowsAndColumns is called in updateDisplayList and during scrolling.
         *  In updateDisplayList it is called before configuring the scrollBars hence is a good place
         *  to determine about scroll bar requirement and maxScrollPosition
         */
        override protected function makeRowsAndColumns(left:Number, top:Number,
                                          right:Number, bottom:Number,
                                          firstColumn:int, firstRow:int,
                                          byCount:Boolean = false,
                                          rowsNeeded:uint = 0):Point
        {
            var retPoint:Point = super.makeRowsAndColumns(left, top, right, bottom,
                    firstColumn, firstRow, byCount, rowsNeeded);
           
            // check if hScrollBar is required.
            if (originalPolicy == ScrollPolicy.AUTO && horizontalScrollForVisibleItems)
            {
                var widthRequired:Number = measureWidthOfItems(verticalScrollPosition, rowCount);
                var availableWidth:Number = width - viewMetrics.left - viewMetrics.right;
                if (widthRequired >= availableWidth)
                {
                    super.horizontalScrollPolicy = ScrollPolicy.ON;   
                    // if we are measuring only visible items then we don't want to
                    // reduce below the previously computed value.
                    maxHorizontalScrollPosition =  Math.max(maxHorizontalScrollPosition,
                                                        widthRequired - availableWidth);
                }
            }

            return retPoint;           
        }
       
        /**
         *  If the maxHorizontalScrollPosition is not changing no action is required.
         */
        override public function set maxHorizontalScrollPosition(value:Number):void
        {
            if( maxHorizontalScrollPosition == value)
                return;
            super.maxHorizontalScrollPosition = value;
        }
       
        /**
         * If we desire to measure only the visible items in the List and set
         * maxHorizontalPosition we handle it here.
         */
        protected function vScrollHandler(event:ScrollEvent):void
        {
            if (event.direction == "vertical" && originalPolicy == ScrollPolicy.AUTO)
            {
                var widthRequired:Number ;
                if (horizontalScrollForVisibleItems)
                    widthRequired = measureWidthOfItems(verticalScrollPosition, rowCount);
                else
                    widthRequired = measureWidthOfItems(0);

                var availableWidth:Number = width - viewMetrics.left - viewMetrics.right;
                if (widthRequired > availableWidth)
                {  
                    if (!horizontalScrollBar)
                        super.horizontalScrollPolicy = ScrollPolicy.ON;   
                    maxHorizontalScrollPosition =  Math.max(maxHorizontalScrollPosition, widthRequired - availableWidth);
                }
            }
        }
       
        /**
         * If collection is reset and if horizontalScrollPolicy is set to AUTO
         * remove the horizontal scroll bar as it may not be necessary for new data.
         */
        override protected function collectionChangeHandler(event:Event):void
        {
            if (event is CollectionEvent && originalPolicy == ScrollPolicy.AUTO)
            {
                var ce:CollectionEvent = CollectionEvent(event);
                if (ce.kind == CollectionEventKind.RESET)           
                {
                    maxHorizontalScrollPosition = 0;
                    super.horizontalScrollPolicy = ScrollPolicy.OFF;
                    if (!horizontalScrollForVisibleItems)
                    {
                        var widthRequired:Number = measureWidthOfItems(0);
                        var availableWidth:Number = width - viewMetrics.left - viewMetrics.right;
                        if (widthRequired >= availableWidth)
                        {
                            super.horizontalScrollPolicy = ScrollPolicy.ON;   
                            // we don't want to set maxHorizontalScrollPosition below zero
                            maxHorizontalScrollPosition =  Math.max(0, widthRequired - availableWidth);
                        }
                    }                   
                }
            }
            super.collectionChangeHandler(event);
        }
       
    ]]>
</mx:Script>

</mx:List>