s: список UIComponent не рендерится хорошо с помощью пользовательского ItemRenderer - PullRequest
0 голосов
/ 27 ноября 2011

Я создал собственный ItemRenderer для s: list, чтобы он содержал список UIComponent, который содержит MovieClip. При прокрутке некоторые элементы не отображаются / отображаются, хотя их свойства parent / 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>

Позиционирование UIComponent или data.getDisplay (), который возвращает MovieClip, не является проблемой. Я использую removeChildAt, чтобы удалить последний мувиклип, использованный этим элементом, и поместил новый. Это работает, только некоторые случайные элементы не отображаются во время прокрутки, а затем при повторной прокрутке появляется .. случайно.

Пожалуйста, помогите .. Спасибо.

Ответы [ 2 ]

2 голосов
/ 28 ноября 2011

У вас много кода.Я расскажу более подробно, но суть в том, что вы не меняете свой компонент, когда изменяется свойство data вашего рендерера.Таким образом, как средство визуализации узнает, когда нужно изменить отображаемые значения?

Итак, первый комментарий заключается в том, что во время первоначальной визуализации компонента List часто создается один модуль визуализации.Нет ничего необычного в том, что дважды происходит срабатывание creationComplete.

Второй комментарий заключается в том, что creationComplete часто является ужасным местом для любого кода инициализации.Прочтите информацию о жизненном цикле компонентов Flex для Spark или Halo .Событие pre-initialize лучше, или событие initialze, если вы хотите получить доступ к дочерним элементам компонента.

В-третьих, вам нужно изучить и прочитать о повторном использовании рендера .Суть в том, что при прокрутке списка каждый рендерер используется повторно.Данные изменяются.Это не создано снова.Компонент List просто передает новые данные и ожидает, что средство визуализации знает, что делать.Ваш код creationComplete, скорее всего, должен будет перейти к обработчику событий dataChange.

В-четвертых, вы должны использовать жизненный цикл Flex Component.Похоже, что ваши методы отображения рендеринга и изменения размера должны переместиться в updateDisplayList (), который должен обрабатывать размеры и расположение дочерних компонентов.

Потребуется довольно много времени, чтобы переписать ваш рендерер;поэтому я сдался на полпути.Но, прочитайте некоторые ссылки, которые я предоставил, расскажите о них и вернитесь, если у вас есть проблемы.

0 голосов
/ 27 ноября 2011

Откуда вы это звоните?Не похоже, что вы используете жизненный цикл компонента, чтобы обновлять данные рендерера при их изменении.Если вы разместите больше кода, будет проще предложить более конкретные предложения, чем «вы должны установить флаг при изменении данных, затем использовать commitProperties, updateDisplaylist и измерение, чтобы отразить изменение».

...