s:自定义ItemRenderer无法很好地呈现UIComponent列表

时间:2011-11-27 14:23:52

标签: list flex flex-spark uicomponents

我为s:list创建了一个自定义ItemRenderer,它包含一个包含MovieClip的UIComponent列表。当我滚动时,一些项目未显示/呈现,尽管它们的父/ x / y属性是正确的。这是列表的ItemRenderer的代码。触发render事件时发生render():

<?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" 
            autoDrawBackground="true" creationComplete="init();" render="render();">

<s:Label id="lbl" text="{data.getName()}" width = "{width}" fontSize="14"/>

<fx:Script>
    <![CDATA[
        import Types.ReversingMovieClip;

        import mx.core.UIComponent;

        private var exDisplay:DisplayObject;
        private var inited:Boolean = false;
        private var uic:UIComponent = new UIComponent();

        public function init():void
        {
            // first item is firing creationComplete twice !
            if (!inited)
            {
                exDisplay = data.getDisplay();
                // Dangerous. if exDisplay has a different event of CLICK, it won't set it here.
                // On the other hand.. this happens at the startup.. so.. what to do.
                if (exDisplay is ReversingMovieClip && !exDisplay.hasEventListener(MouseEvent.CLICK))
                    exDisplay.addEventListener(MouseEvent.CLICK, playPauseClip);
                inited = true;
                addElement(uic);
            }
        }

        public function render():void
        {
            if (exDisplay != null && exDisplay.parent == uic)
                uic.removeChild(exDisplay);

            exDisplay = data.getDisplay();

            //if (exDisplay.width != width && exDisplay.height != width)
                resizeDisplay();

            uic.width = exDisplay.width;
            uic.height = exDisplay.height;


            uic.addChild(exDisplay);


            //ReversingMovieClip.setPlayBySpeed(true);
            //ReversingMovieClip.setSpeed(1);
        }

        private function resizeDisplay():void
        {

            if (exDisplay.width > exDisplay.height)
            {
                exDisplay.width = width;
                exDisplay.scaleY = exDisplay.scaleX;
            }
            else
            {
                exDisplay.height = width;
                exDisplay.scaleX = exDisplay.scaleY;
                exDisplay.x = width / 2 - exDisplay.width / 2;
            }
            uic.y = 12;
            /* trace("listw " + width + "\nexHeight " + exDisplay.height + "exWidth " + 
                exDisplay.width + "\nuicW " + uic.width + " " + uic.height); */

        }

        private function playPauseClip(e:Event):void
        {
            var mc:ReversingMovieClip = (e.currentTarget as ReversingMovieClip);
            if (mc.isPlaying())
                mc.stop();
            else mc.play();
        }
    ]]>
    </fx:Script>

</s:ItemRenderer>

返回MovieClip的UIComponent或data.getDisplay()的定位不是问题。 我使用removeChildAt删除此项目使用的最后一个MovieClip,并添加新项目。 它有效,只有滚动时没有显示的一些随机项目,然后当你再次滚动时,它会随机出现..

请帮忙..谢谢。

2 个答案:

答案 0 :(得分:2)

你有很多代码。我将更深入地了解一下,但要点是,当渲染器的data属性发生更改时,您不会更改组件。因此,渲染器将如何知道何时更改它显示的值?

因此,首先评论是在List组件的初始渲染过程中经常创建单个渲染器。看到creationComplete两次火灾并不罕见。

第二个评论是,对于任何初始化代码,creationComplete通常都是一个可怕的地方。阅读适用于SparkHalo的Flex Component LifeCycle。如果您想要访问组件的子项,则pre-initialize事件更好,或者是initialze事件。

第三,你需要研究和阅读render recycling。要点是,当您滚动列表时,每个渲染器都会被重复使用。数据发生了变化。它不是再创建的。 List组件只传入新数据,并期望渲染器知道该怎么做。您的“creationComplete”代码很可能需要移动到dataChange事件处理程序。

第四,你应该使用Flex Component LifeCycle。看起来你的渲染和调整大小显示方法应该进入updateDisplayList(),它应该处理组件子节点的大小和位置。

重新编写渲染器需要花费相当多的时间;所以我放弃了一半。但是,阅读我提供的一些链接,给它一个解决方法,如果你有问题,请回来。

答案 1 :(得分:0)

你在哪里打电话给这个?当数据发生变化时,您似乎正在利用组件生命周期来更新渲染器数据。如果您发布更多代码,提供更具体的建议比“您应该在数据更改时设置标志,然后使用commitProperties,updateDisplaylist和measure来反映更改。”