s:UIComponent 列表未通过自定义 ItemRenderer 很好地呈现

发布于 2024-12-18 09:20:29 字数 3159 浏览 0 评论 0原文

我为 as:list 创建了一个自定义 ItemRenderer,让它包含一个包含 MovieClip 的 UIComponent 列表。当我滚动时,某些项目未显示/渲染,尽管它们的父/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,并放置新的。 它有效,只是一些随机项目在滚动时不显示,然后当您再次滚动时,它们会随机出现。

请帮忙..谢谢。

I created a custom ItemRenderer for a s:list, for it to contain a list of UIComponent which contains a MovieClip. When I scroll some of the items are not shown/rendered, although their parent/x/y properties are correct. here is the code of the list's ItemRenderer. render() occurs when render event is triggered :

<?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>

The positioning of the UIComponent or the data.getDisplay() which returns the MovieClip is not the problem.
I use removeChildAt to remove the last MovieClip used by this item, and put the new one.
It works, only that some random items not showing while scrolling, and then when you scroll again the do appear.. randomly.

Please help.. Thank you.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

半城柳色半声笛 2024-12-25 09:20:29

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

因此,第一个评论是,在 List 组件的初始渲染期间通常会创建单个渲染器。看到创作完成两次火灾并不罕见。

第二条评论是,对于任何初始化代码来说,creationComplete 通常都是一个可怕的地方。阅读 Spark 或 <一个href="http://livedocs.adobe.com/flex/3/html/help.html?content=ascomponents_advanced_2.html" rel="nofollow">光环。如果您想访问组件的子组件,则预初始化事件更好,或者初始化事件更好。

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

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

重新编写渲染器将花费相当多的时间;所以我半途放弃了。但是,请仔细阅读我提供的一些链接,尝试一下,如果遇到问题再回来。

You have a lot of code. I'll take a more in depth look, but the gist is that you are not changing your component when the data property of your renderer changes. As such, how will the renderer know when to change the values it displays?

So, first comment is that a single renderer is often created during the List component's initial rendering. This is not unusual to see a creationComplete fire twice.

Second comment is that creationComplete is often a horrible place for any initializing code. Read up on the Flex Component LifeCycle for Spark or Halo. The pre-initialize event is better, or the the initialze event if you want to access a component's children.

Third, you need to research and read about render recycling. The gist is that as you scroll through the list, each renderer is re-used. The data changes. It is not created again. The List component just passes in new data and expects the renderer to know what to do. Your 'creationComplete' code will most likely need to move to a dataChange event handler.

Fourth you should make use of the Flex Component LifeCycle. It looks like your render and resize display methods should move into updateDisplayList() which is supposed to handle sizing and positioning of the components children.

It's going to take quite a bit of time to re-write your renderer; so I gave up half way through. But, read through some of the links I provided, give a crack at it and come back if you have problems.

感受沵的脚步 2024-12-25 09:20:29

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

Where are you calling this from? It doesn't look like you're leveraging the component life cycle to make your renderer data update when the data changes. If you post more code, it will be easier to offer more specific suggestions than "you should set a flag when the data changes, then use commitProperties, updateDisplaylist, and measure to reflect the change."

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文