In the good old mx world, the alternatingItemColors extend all the way to the height of the list. In the spark list, it stops where the data ends. Does anyone know if there is an easy way to make the Spark list behave similar to the mx list? See the image below. there is white space below the list, this does not happen in the mx list.
The difficulty will depend on how flexible your solution must be, but in general I think your best bet would be to create a custom skin for this List.
You can start by copying the Spark List skin (spark.skins.spark.ListSkin) and making some minor modifications to it:
<!-- AlternatingColorListSkin.mxml -->
<s:Skin xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark">
<fx:Metadata>
[HostComponent("spark.components.List")]
</fx:Metadata>
<s:states>
<s:State name="normal"/>
<s:State name="disabled"/>
</s:states>
<s:Rect id="background" left="0" right="0" top="0" bottom="0">
<s:fill>
<s:SolidColor id="bgFill" color="0xEEEEEE"/>
</s:fill>
<s:stroke>
<s:SolidColorStroke id="borderStroke" weight="1"/>
</s:stroke>
</s:Rect>
<s:Group id="oddRowGroup" left="1" right="1" top="1" bottom="1" clipAndEnableScrolling="true"/>
<s:Scroller id="scroller" left="0" top="0" right="0" bottom="0" minViewportInset="1" hasFocusableChildren="false">
<s:DataGroup id="dataGroup" itemRenderer="spark.skins.spark.DefaultItemRenderer">
<s:layout>
<s:VerticalLayout id="dataLayout" gap="0" horizontalAlign="contentJustify" requestedMinRowCount="5"/>
</s:layout>
</s:DataGroup>
</s:Scroller>
</s:Skin>
In the code above I left out the portions of ListSkin that are irrelevant to this answer and I made these modifications:
dataLayout
) so that we can easily access it laterWe'll now be adding the odd row backgrounds to oddRowGroup
dynamically. Note that oddRowGroup
's left/right/top/bottom is 1 so that the row backgrounds will not overlap the main background's border. It also has clipAndEnableScrolling
set to true
which will cause any possible overlap of the last odd row to be clipped.
Now add the following code in a script block in the skin:
private var previousHeight:Number = NaN;
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void {
super.updateDisplayList(unscaledWidth, unscaledHeight);
if (previousHeight != unscaledHeight) refreshBackground(unscaledHeight);
previousHeight = unscaledHeight;
}
private function refreshBackground(height:Number):void {
var rowHeight:Number = dataLayout.rowHeight;
var maxRows:int = height / rowHeight / 2;
oddRowGroup.removeAllElements();
for (var i:int = 0; i < maxRows; i++) {
var row:FilledElement = new Rect();
row.left = row.right = 0;
row.height = rowHeight;
row.top = (i * 2 + 1) * rowHeight;
row.fill = new SolidColor(0xdfdfdf);
oddRowGroup.addElement(row);
}
}
What happens here?
In updateDisplayList
(which is called amongst others each time the List is resized), we check whether the height has changed. If it has, we refresh the odd row backgrounds.
We do so by removing all backgrounds that were drawn for the previous height.
We get the rowHeight
from the DataGroup's layout, and we calculate the total number of required backgrounds. Then we create some Rect
s based on these numbers and we add them to oddRowGroup
.
The solution as it is, has some limitations. For instance the alternating colors are hardcoded (which can easily fixed by getting the right colors using getStyle()
); it assumes there will be no override of the default layout (which is a VerticalLayout
); it assumes variableRowHeight
is off; and probably some more. But I think it's a good starting point.