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>