Reputation: 8159
Apologies for the vague title. I could not think of a better way to word it in so few words.
Basically, I am creating a custom ItemRenderer (IR). The IR has a label on the left side and an icon on the right side. The icon on the right side is dynamic (can be either an add or remove icon or nothing at all). This works beautifully and gives me the control I need over it.
Now, the problem is that when I scroll the list in my mobile application, the icons change.
How it should look:
How it looks after scrolling using a finger (or mouse in emulator) by dragging on Test3:
As you can see, the icons change but the labels do not. I have dragEnabled
, dropEnabled
, and dragMoveEnabled
all set to false on my Spark List component. The only time the icon selection runs is on creationComplete
, so there is no way it is choosing a different icon at some point. I can also verify that the data itself is what it should be after this change occurs.
Here is the MXML that creates the item:
<s:HGroup width="100%" verticalAlign="middle" left="{this.sideSpacing}" right="{this.sideSpacing}" top="{this.sideSpacing}" bottom="{this.sideSpacing}">
<s:Label id="text" width="100%"/>
<s:Image id="actionIcon" buttonMode="true" click="actionIconClick( event );">
<s:filters>
<s:DropShadowFilter alpha=".45" angle="90" distance="3" blurX="3" blurY="3" quality="3"/>
</s:filters>
</s:Image>
</s:HGroup>
<s:Rect width="100%" height="1" bottom="0" alpha=".1">
<s:fill>
<s:SolidColor color="#000000"/>
</s:fill>
</s:Rect>
And the possibly over-elaborate AS3 for selecting which icon should be displayed:
private function creationComplete( e:Event ):void {
if ( this.data.actionIcon != null ) {
this.actionIconType = this.data.actionIcon;
if ( this.data.actionIcon == ACTION_ICON_ADD ) {
this.actionIcon.source = this.addBitmapSource;
}
else if ( this.data.actionIcon == ACTION_ICON_REMOVE ) {
this.actionIcon.source = this.removeBitmapSource;
}
else {
this.actionIcon.source = null;
this.actionIcon.visible = false;
this.actionIcon.includeInLayout = false;
}
}
else {
this.actionIcon.source = null;
this.actionIcon.visible = false;
this.actionIcon.includeInLayout = false;
}
}
What could be causing this issue?
Upvotes: 0
Views: 505
Reputation: 39408
Basically, you need to update your renderer's label and icon when the dataChange event is fired. CreationComplete is only fired once. The list isn't really scrolled, just that the data in the itemRenderers change; causing it to look like things are scrolling. I call this renderer recycling.
Here is a component I created for a mobile app that does what you want. It displays a label and an icon (AKA the Decorator). When scrolling the label and icon are both updated. You can use a very similar approach.
<?xml version="1.0" encoding="utf-8"?>
<s:IconItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
dataChange="onDataChange(event)" alpha=".7" width="100%" cacheAsBitmap="true">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<fx:Script>
<![CDATA[
import com.dotcomit.magondaMaze.managers.BoardDataManager;
import com.dotcomit.magondaMaze.managers.StatManager;
import mx.events.FlexEvent;
[Embed(source="assets/images/chooseLevel/completed78x78.png")]
private var completedImage:Class;
public var statManager :StatManager = StatManager.instance;
protected function onDataChange(event:FlexEvent):void
{
var itemAsXML :XML = data as XML;
var results :String = itemAsXML.@id + '. ' + itemAsXML.@title;
label = results;
if( statManager.isBoardComplete(itemAsXML.@id)){
this.decorator = completedImage;
} else {
this.decorator = null;
}
}
]]>
</fx:Script>
</s:IconItemRenderer>
I'll also add that the IconItemRenderer component--which my code above extends--is designed to do exactly what you need. So, you may not have to re-write the wheel so to speak.
Upvotes: 3