0

我已经创建了自定义IconItemRenderer标签和消息显示在图标上(在我的情况下它是一个大图像)。我想在加载图像期间隐藏标签和消息。所以我默认让它们不可见。当图像被加载时,我让它们可见。

override protected function layoutContents(unscaledWidth:Number, unscaledHeight:Number):void
{
    super.layoutContents(unscaledWidth, unscaledHeight);

    setElementPosition(busyIndicator, (this.width - iconDisplay.width) / 2, (this.height - Dimensions.BUSY_INDICATOR_EDGE_LENGTH) / 2);
    setElementPosition(iconDisplay, (this.width - iconDisplay.width) / 2, 0);
    setElementPosition(labelDisplay, iconDisplay.x + 20, iconDisplay.y + iconDisplay.height / 4);
    setElementPosition(textFieldProductNumber, iconDisplay.x + 20, labelDisplay.y + labelDisplay.height + 10); 
    setElementPosition(messageDisplay, iconDisplay.x + 20, textFieldProductNumber.y + textFieldProductNumber.height);

    setElementSize(busyIndicator, Dimensions.BUSY_INDICATOR_EDGE_LENGTH, Dimensions.BUSY_INDICATOR_EDGE_LENGTH);
    setElementSize(textFieldProductNumber, labelDisplay.width, labelDisplay.height / 2);

    iconDisplay.addEventListener(Event.COMPLETE, onIconComplete);

    if(!isIconComplete)
    {
        busyIndicator.visible = true;
        iconDisplay.visible = false;
        labelDisplay.visible = false;
        textFieldProductNumber.visible = false;
        messageDisplay.visible = false;

    }
}

protected function onIconComplete(event:Event):void
{

    busyIndicator.visible = false;
    iconDisplay.visible = true;
    labelDisplay.visible = true;
    textFieldProductNumber.visible = true;
    messageDisplay.visible = true;  

    isIconComplete = true;

    iconDisplay.removeEventListener(Event.COMPLETE, onIconComplete);

    invalidateDisplayList();

}

一切正常,但是如果我将另一个视图推入Navigator并返回到我的 IconItemRenderer 所在的视图,系统会创建另一个 IconItemRenderer 实例,并且标签、消息或图像也不可见(因为我的默认值)。

那么如何使用较早的cratedIconItemRenderer实例呢?

或者是否可以使用单个 IconItemRenderer实例(如单音)?

或者是否有任何表明项目中的数据已经存在?Event Dispathcer

4

2 回答 2

0

Note that as an optimization for mobile devices, I believe the mobile item renderer classes do some caching of images (unlike on the web, where it just relies on the images being in the browser cache). This is likely why you don't get another COMPLETE event.

So how can I use earlier created IconItemRenderer instance?

You shouldn't try or expect to reuse an earlier instance of the render. The Flex List control uses object pooling to recycle item renderers. The list creates as many renderers as needed to display the content on screen. When you scroll the list, it re-uses these renderers to display the new elements that have scrolled into view (more on this in a moment). You shouldn't try to circumvent this behavior, it's pretty efficient :)

or is it possible to use single IconItemRenderer instance (like a singleton)?

No, as stated above, the list uses object pooling and re-uses the renderer instances it creates as it sees fit. The singleton pattern really doesn't apply here.

or is there any Event Dispathcer which indicates that data in item already exists?

I'm not aware of an event that says "hey this image has already been loaded". However, when Flex uses an item renderer (whether it's the first time or when it's being re-used), it will set the data property of the renderer. The setter for the data property dispatches a "dataChange" event.

So you can listen for this event or override the setter for the data property to know when the renderer is getting it's data. Now you have a two fold approach you can use:

When the data is set, determine if the data being passed in is calling for a new image or one that was previously displayed. If the data is different, listen for the COMPLETE event to know when the image is loaded as you're currently doing.

If the data is the same as before, just make the label/message objects visible.

This may or may not work... another idea is when the data is set, to try and infer if the image has been loaded by checking the bytesLoaded or bitmapData properties of the image.

By doing this sort of thing, you can make the image/label/message objects visible in the overridden setter method for data (or the event handler for the "dataChange" event) to handle cases where the image has already been loaded.

于 2013-02-11T08:25:37.183 回答
0
override protected function layoutContents(unscaledWidth:Number, unscaledHeight:Number):void
{
   super.layoutContents(unscaledWidth, unscaledHeight);

   setElementPosition(busyIndicator, (this.width - iconDisplay.width) / 2, (this.height - Dimensions.BUSY_INDICATOR_EDGE_LENGTH) / 2);
   setElementPosition(iconDisplay, (this.width - iconDisplay.width) / 2, 0);
   setElementPosition(labelDisplay, iconDisplay.x + 20, iconDisplay.y + iconDisplay.height / 4);
   setElementPosition(textFieldProductNumber, iconDisplay.x + 20, labelDisplay.y + labelDisplay.height + 10); 
   setElementPosition(messageDisplay, iconDisplay.x + 20, textFieldProductNumber.y + textFieldProductNumber.height);

   setElementSize(busyIndicator, Dimensions.BUSY_INDICATOR_EDGE_LENGTH, Dimensions.BUSY_INDICATOR_EDGE_LENGTH);
   setElementSize(textFieldProductNumber, labelDisplay.width, labelDisplay.height / 2);

   if(iconContentLoader)
       ContentCache(iconContentLoader).enableCaching = false;

   iconDisplay.addEventListener(Event.COMPLETE, onIconComplete);

   if(!isIconComplete)
   {
       busyIndicator.visible = true;
       iconDisplay.visible = false;
       labelDisplay.visible = false;
       textFieldProductNumber.visible = false;
       messageDisplay.visible = false;

   }
}

protected function onIconComplete(event:Event):void
{

   busyIndicator.visible = false;
   iconDisplay.visible = true;
   labelDisplay.visible = true;
   textFieldProductNumber.visible = true;
   messageDisplay.visible = true;  

   isIconComplete = true;


   iconDisplay.removeEventListener(Event.COMPLETE, onIconComplete);

   invalidateDisplayList();

}

我认为这将解决问题

于 2013-06-27T13:17:18.233 回答