سؤال

I've extended IconItemRenderer to create a custom item renderer needed for a project I am working on. The renderer works fine right now, except I cannot figure out how to add more images beyond the icon and decorator. I need to add three additional images and cannot figure out how.

What I have been trying (the renderer is entirely written in AS3):

override protected function createChildren():void {
    super.createChildren();
    this.downloadIcon = new BitmapImage();
    this.downloadIcon.source = "assets/images/download-160.png";
    var down:DisplayObject = this.downloadIcon.createDisplayObject();
    this.addChild( down );
}

As far as I can tell, that should work. If I load that source as the iconDisplay source, it loads just fine so it isn't the source. It also does not matter what source I use (or even local vs external). I have also tried using code from the IconItemRenderer source to no avail:

private function assignDisplayObject(bitmapImage:BitmapImage):void
{
    if (bitmapImage)
    {
        // try using this display object first
        if (bitmapImage.setSharedDisplayObject(this))
        {
            bitmapImage.displayObjectSharingMode = DisplayObjectSharingMode.USES_SHARED_OBJECT;
        }
        else
        {
            // if we can't use this as the display object, then let's see if 
            // the icon already has and owns a display object
            var ownsDisplayObject:Boolean = (bitmapImage.displayObjectSharingMode != DisplayObjectSharingMode.USES_SHARED_OBJECT);

            // If the element doesn't have a DisplayObject or it doesn't own
            // the DisplayObject it currently has, then create a new one
            var displayObject:DisplayObject = bitmapImage.displayObject;
            if (!ownsDisplayObject || !displayObject)
                displayObject = bitmapImage.createDisplayObject();

            // Add the display object as a child
            // Check displayObject for null, some graphic elements
            // may choose not to create a DisplayObject during this pass.
            if (displayObject)
                addChild(displayObject);

            bitmapImage.displayObjectSharingMode = DisplayObjectSharingMode.OWNS_UNSHARED_OBJECT;
        }
    }        
}

Nothing displays using either method. Could someone explain what I am doing wrong with this?

Using Flex 4.10 and AIR 3.8 if that helps at all.

EDIT: As requested by Reboog, here is the full item renderer minus imports

public class VideoItemRenderer extends IconItemRenderer
{
private static const OUTER_PADDING:uint = 15;
private static const INNER_PADDING:uint = 10;

private var description:StyleableTextField;
private var progressBar:ProgressBar;
private var downloadContainer:Group;
private var deleteIcon:VideoDeleteIcon;
private var downloadIcon:Image;

public function VideoItemRenderer()
{
    super();

    this.addEventListener( FlexEvent.DATA_CHANGE, this.dataChangeHandler );
    this.minHeight = 106;
    this.iconFunction = this.iconSelectFunction;
    this.iconHeight = 76;
    this.iconWidth = 107;
}

private function iconSelectFunction( item:Object ):Object {
    return "assets/images/background-160.png";
}

override protected function createChildren():void {
    super.createChildren();

    this.labelDisplay.wordWrap = true;
    this.labelDisplay.multiline = true;

    this.description = StyleableTextField(createInFontContext(StyleableTextField));
    this.description.styleName = this;
    this.description.editable = false;
    this.description.selectable = false;
    this.description.multiline = true;
    this.description.wordWrap = true;
    this.description.setStyle( "fontFamily", "josefin" );
    this.description.setStyle( "fontWeight", "bold" );
    this.description.text = "Vestibulum id ligula porta felis euismod semper. Cras mattis consectetur purus sit amet.";
    this.addChild( this.description );

    this.deleteIcon = new VideoDeleteIcon();
    this.deleteIcon.addEventListener( MouseEvent.CLICK, this.deleteClickHandler );
    this.addChild( this.deleteIcon );

    this.downloadContainer = new Group();
    this.addChild( this.downloadContainer );

    this.progressBar = new ProgressBar();
    this.downloadContainer.addChild( this.progressBar );

    this.downloadIcon = new Image();
    this.downloadIcon.source = "assets/images/download-160.png";
    this.downloadContainer.addChild( downloadIcon );
}

override protected function drawBackground(unscaledWidth:Number, unscaledHeight:Number):void {
    unscaledWidth = Math.min( this.owner.width, unscaledWidth );

    graphics.beginFill( 0xffffff, .1 );
    graphics.drawRect( 0, 0, unscaledWidth, unscaledHeight );
    graphics.endFill();
    opaqueBackground = null;
}

override protected function layoutContents(unscaledWidth:Number, unscaledHeight:Number):void {
    unscaledWidth = Math.min( this.owner.width, unscaledWidth );
    super.layoutContents( unscaledWidth, unscaledHeight );

    if ( this.iconDisplay ) {
        this.setElementSize( this.iconDisplay, 107, 76 );
        this.setElementPosition( this.iconDisplay, OUTER_PADDING, OUTER_PADDING );

        this.setElementPosition( this.labelDisplay, this.iconDisplay.x + this.getElementPreferredWidth( this.iconDisplay ) + INNER_PADDING, OUTER_PADDING );
        this.setElementPosition( this.description, this.iconDisplay.x + this.getElementPreferredWidth( this.iconDisplay ) + INNER_PADDING, this.labelDisplay.y + this.getElementPreferredHeight( this.labelDisplay ) + INNER_PADDING );
    }
    else {
        this.setElementPosition( this.labelDisplay, OUTER_PADDING, OUTER_PADDING );
        this.setElementPosition( this.description, OUTER_PADDING, this.labelDisplay.y + this.getElementPreferredHeight( this.labelDisplay ) + INNER_PADDING );
    }
    this.setElementSize( this.labelDisplay, unscaledWidth - this.labelDisplay.x - OUTER_PADDING, this.getElementPreferredHeight( this.labelDisplay ) );
    this.setElementSize( this.description, unscaledWidth - this.description.x - OUTER_PADDING, this.getElementPreferredHeight( this.description ) );
    this.setElementPosition( this.deleteIcon, unscaledWidth - this.getElementPreferredWidth( this.deleteIcon ), 0 );

    var descriptionHeight:Number = this.description.y + this.getElementPreferredHeight( this.description );
    var iconHeight:Number = this.iconDisplay ? this.iconDisplay.y + this.getElementPreferredHeight( this.iconDisplay ) : 0;

    //this.setElementSize( this.progressBar, this.description.width, 5 );
    this.progressBar.width = this.description.width;
    this.setElementPosition( this.downloadContainer, 0,Math.max( descriptionHeight, iconHeight ) + OUTER_PADDING );
    this.setElementPosition( this.progressBar, this.description.x, ( this.getElementPreferredHeight( this.downloadContainer ) - this.getElementPreferredHeight( this.progressBar ) ) / 2 );

    var downloadHeight:Number = this.getElementPreferredHeight( this.downloadContainer ) + this.downloadContainer.y;
    this.height = downloadHeight + OUTER_PADDING;
}

private function dataChangeHandler( e:FlexEvent ):void {
    if ( this.data ) {
        this.label = this.data.label.toUpperCase();
    }
}
}
هل كانت مفيدة؟

المحلول

Ok, so I managed to figure out what was going on.

Originally, I tried adding the image to the downloadContainer which was a Sprite (honest mistake on my part; just finished an AS3 project last week). It appears that using downloadContainer.addChild(Image) does not appear to be possible, which is why IconItemRenderer uses BitmapImage#createDisplayObject() and adds the created DisplayObject.

I switched the container to a Group, used addElement, and made ProgressBar extend UIComponent instead of Sprite and everything worked as I believed it should have originally.

So use this:

var container:Group = new Group();
addChild( container );
var image:Image = new Image();
image.source = "blah.png";
container.addElement( image );

That will successfully add the image.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top