0

我为 as:list 创建了一个自定义 ItemRenderer,它包含一个 UIComponent 列表,其中包含一个 MovieClip。当我滚动时,一些项目没有显示/渲染,尽管它们的 parent/x/y 属性是正确的。这是列表的 ItemRenderer 的代码。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>

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

请帮忙..谢谢。

4

2 回答 2

2

你有很多代码。我将进行更深入的研究,但要点是当渲染器的数据属性发生更改时,您不会更改组件。因此,渲染器如何知道何时更改其显示的值?

因此,第一个评论是,在 List 组件的初始渲染期间通常会创建单个渲染器。看到一个creationComplete 火了两次并不稀奇。

第二条评论是,creationComplete 通常是任何初始化代码的可怕地方。阅读SparkHalo的 Flex 组件生命周期。pre-initialize 事件更好,如果您想访问组件的子级,则使用 initialze 事件。

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

第四,您应该使用 Flex 组件生命周期。看起来您的渲染和调整大小显示方法应该移到 updateDisplayList() 中,该方法应该处理子组件的大小调整和定位。

重新编写渲染器需要相当长的时间;所以我中途放弃了。但是,请阅读我提供的一些链接,试一试,如果有问题再回来。

于 2011-11-28T03:16:21.780 回答
0

你是从哪里打电话来的?看起来您并没有利用组件生命周期来在数据更改时更新渲染器数据。如果您发布更多代码,则提供更具体的建议会比“您应该在数据更改时设置一个标志,然后使用 commitProperties、updateDisplaylist 和 measure 来反映更改”更容易。

于 2011-11-27T15:09:58.903 回答