开发者

Flex 4 ItemRenderer in Spark List Ghosting Issue when scrolling

开发者 https://www.devze.com 2023-03-18 11:52 出处:网络
I have an item renderer in a list, when I try to use the override method to setup the list items how I want them they are invisible.

I have an item renderer in a list, when I try to use the override method to setup the list items how I want them they are invisible.

When I try to use the function to set them up, every time I scroll the list consuming the renderer, it starts giving serious redraw problems.

When I combine both methods the Labels redraw correctly but the images ghost them selves up and down as I scroll.

Here is the code:

http://pastebin.com/FkjRBT3G

Please and thank you to any help you can give.

Edit most recent code

    <?xml version="1.0" encoding="utf-8"?>
<s:ItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009" 
                xmlns:s="library://ns.adobe.com/flex/spark" 
                xmlns:mx="library://ns.adobe.com/flex/mx" creationComplete="setupControls();"  autoDrawBackground="true" contentBackgroundAlpha="1.0" contentBackgroundColor="#000000">

    <fx:Script>
        <![CDATA[
            import flash.display.*;
            import flash.ui.ContextMenu;
            import flash.ui.ContextMenuBuiltInItems;
            import flash.ui.ContextMenuItem;

            import mx.controls.Alert;
            import mx.core.FlexGlobals;

        /*  override public function set data(value:Object):void{
                if(value != null)  {
                    super.data = value;
                    theLabel.text = value.UserName;
                    if (value.IsGroup == true){
                        imgGroup.visible=true;
                        theLabel.x = 24;
                        theLabel.setStyle("fontWeight", "bold")
                    }

                    if (value.IsGroup  == false){
                        imgUser.visible=true;
                 开发者_C百科       theLabel.x = 34;
                    }
                }
            }  */

        private function setupControls():void{
                    theLabel.text = data.UserName;
                    theLabel.y = 4;
                    if (data.IsGroup == 'true'){
                        imgGroup.visible=true;
                        theLabel.x = 24;
                        theLabel.setStyle("fontWeight", "bold")
                    }

                    if (data.IsGroup  == 'false'){
                        imgUser.visible=true;
                        theLabel.x = 34;
                    }

                    var availableFieldMenu:ContextMenu = new ContextMenu();
                    var chartSubTypeFieldMenu:ContextMenuItem = new ContextMenuItem("Add, Edit, Delete",false,true,true);
                    availableFieldMenu.customItems.push(chartSubTypeFieldMenu);
                    chartSubTypeFieldMenu.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, menuItemHandler);
                    availableFieldMenu.hideBuiltInItems();
                    this.contextMenu = availableFieldMenu;
                }   


        public function menuItemHandler(event:ContextMenuEvent) : void{
            if (event.currentTarget.caption=="Add, Edit, Delete"){
                Alert.show('Right Click Just Happened!');
            }
        }




        ]]>
    </fx:Script>


    <s:Label y="4" id="theLabel" color="#000000"/><mx:Image id="imgGroup" source="@Embed(source='file:/D:/Work/RapidReport/Images/nd0071-16.png')"  width="16" height="16" x="3" visible="false" buttonMode="true"/><mx:Image id="imgUser" source="@Embed(source='file:/D:/Work/RapidReport/Images/nd0032-48.png')" width="16" height="16" x="13" visible="false"/>

</s:ItemRenderer>

Regards Craig


I fixed it by turning off use virtual layout, the context menus work well actually ;)

The list it self is bound to an xml list using a {}


You can't use a context menu in an item renderer.

Why are you creating all these things on creation complete if it isn't needed right away? Don't use creation complete event, there are new functions for that kind of stuff (for better recycling) like 'prepare'. From what I can see, your whole creation complete function isn't needed.

Bindable is not needed on the data set function.

Here's the cleaned up, untested version:

<?xml version="1.0" encoding="utf-8"?>
<s:ItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009" 
                xmlns:s="library://ns.adobe.com/flex/spark" 
                xmlns:mx="library://ns.adobe.com/flex/mx">

    <fx:Script>
        <![CDATA[
            import flash.display.*;
            import flash.ui.ContextMenu;
            import flash.ui.ContextMenuBuiltInItems;
            import flash.ui.ContextMenuItem;

            import mx.controls.Alert;
            import mx.core.FlexGlobals;

          override public function set data(value:Object):void
          {
                super.data = value;
                label.text = value.UserName;

                if (value.IsGroup)
                {
                    currentState = 'group';
                }else{
                    currentState = 'user';
                }
            }  

            private function onMenu():void
            {
                // TODO: add code to add the menu.  
                // Can't use right click to do this as right click is only for 
                // context menu on top level component. should create 'menu' button
            }  
        ]]>
    </fx:Script>
    <s:layout>
        <s:VerticalLayout gap="0" />
    </s:layout>
    <s:states>
        <s:State name="group" />
        <s:State name="user" />
    </s:states>
    <mx:Image width="16" height="16" buttonMode="true" includeIn="group"
        source="@Embed(source='file:/D:/Work/RapidReport/Images/nd0071-16.png')"  />
    <mx:Image width="16" height="16" includeIn="user"
        source="@Embed(source='file:/D:/Work/RapidReport/Images/nd0032-48.png')" />
    <s:Label id="label" color="#000000" fontWeight.group="bold"/>
</s:ItemRenderer>

You should also post how the data provider/list is created and updated because I'm sure there's other issues.


setupControls is probably redundant now and useVirtualLayout can be true in this instance:

<?xml version="1.0" encoding="utf-8"?>

<fx:Script>
    <![CDATA[
        import flash.display.*;
        import flash.ui.ContextMenu;
        import flash.ui.ContextMenuBuiltInItems;
        import flash.ui.ContextMenuItem;

        import mx.controls.Alert;
        import mx.core.FlexGlobals;

        [Bindable] public var TheState:String=''; 

        override public function set data(value:Object):void{

            if(value != null)  {
                super.data = value;
                if (value.IsGroup == true){
                    TheState = 'group';
                    currentState = 'group';
                    //theLabel.x = 24;
                    //theLabel.setStyle("fontWeight", "bold")
                }

                if (value.IsGroup  == false){
                    TheState  = 'user';
                    currentState = 'user';
                    //theLabel.x = 34;
                }
            }
            //super.invalidateDisplayList();
        }  

        private function setupControls():void{  
            if (String(data.IsGroup)=='true'){

                TheState='group';
            }else {
                TheState='user';
            }
            //Alert.show('' + TheState);
            if (TheState  == 'group'){
                currentState = 'group';
            }

            if (TheState == 'user'){
                currentState = 'user';              
            }   
        }   

        override public function set currentState(value:String):void
        {
            super.currentState = value;

            //if (value != 'normal' && value != 'hovered' && value != 'selected')
            //{
                this.TheState = TheState;
            //}
        }

        override protected function getCurrentRendererState():String
        {
            var state:String = super.getCurrentRendererState();

            state = TheState;
            return state;
        }


    ]]>
</fx:Script>
<s:states>
    <s:State name="default" basedOn="{TheState}" />
    <s:State name="normal" basedOn="{TheState}" />
    <s:State name="hovered" basedOn="{TheState}" />
    <s:State name="selected" basedOn="{TheState}" /> 
    <s:State name="up" basedOn="{TheState}"/>
    <s:State name="over" basedOn="{TheState}"/>
    <s:State name="down" basedOn="{TheState}"/>
    <s:State name="disabled" basedOn="{TheState}"/>  

    <s:State name="user" />
    <s:State name="group" />

</s:states>


<s:Label y="4" x="34" id="theUserLabel" text="{data.UserName}" color="#000000" includeIn="user"/><s:Label text="{data.UserName}"  y="4" x="24" id="theGroupLabel" color="#000000" includeIn="group" fontWeight="bold"/><mx:Image id="imgGroup" source="@Embed(source='file:/D:/Work/RapidReport/Images/nd0071-16.png')"  width="16" height="16" x="3" visible="true" buttonMode="true" includeIn="group"/><mx:Image id="imgUser" source="@Embed(source='file:/D:/Work/RapidReport/Images/nd0032-48.png')" width="16" height="16" x="13" visible="true" includeIn="user"/>


I had the same issue and fixed it the following way:

Decomposed my data to properties and passed property by property to the renderer, so the overridden data function removed, used setters for each data property (decomposed(extracted) from the data).


Question is pretty old, but it seems that the issue still persists in Flex 4.13. I'm struggling with the same issue and I do override the data setter. 2 methods that I use to work around this issue:

  1. use mx:Label instead of Spark's Label
  2. remove the virtual layout in case the list is known to be very small and mostly visible

Also, I did notice that this issue occurs in Spark's DataGrid as well as in List

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号