How to add a background skin to a custom item renderer based on FeathersControl and IListItemRenderer (Starling version)

The example custom item renderer with FeathersControl and IListItemRenderer offers an easy-to-understand foundation to build upon. It's pretty limited in features, though. For instance, you may want some kind of background skin.

If you've created a custom item renderer based on LayoutGroup, you don't need to implement the background skin yourself. You can simply set the backgroundSkin property.

A backgroundSkin getter and setter

Let's start by adding a backgroundSkin property to our custom item renderer class:

private var _backgroundSkin:DisplayObject;
 
public function get backgroundSkin():DisplayObject
{
    return this._backgroundSkin;
}
 
public function set backgroundSkin(value:DisplayObject):void
{
    if(this._backgroundSkin == value)
    {
        return;
    }
    if(this._backgroundSkin)
    {
        this.removeChild(this._backgroundSkin, true);
    }
    this._backgroundSkin = value;
    if(this._backgroundSkin)
    {
        this.addChildAt(this._backgroundSkin, 0);
    }
    this.invalidate(INVALIDATION_FLAG_SKIN);
}

Notice that if an old background skin already exists, we remove it. Then, if the new background skin isn't null, we add it as a child at index 0. This will ensure that the background skin is always at the bottom.

Resizing the background skin

As you may recall, the example custom item renderer based on FeathersControl and IListItemRenderer had a layoutChildren() function. Let's simply set the width and height of the background skin in there.

protected function layoutChildren():void
{
    if(this._backgroundSkin)
    {
        this._backgroundSkin.width = this.actualWidth;
        this._backgroundSkin.height = this.actualHeight;
    }
 
    // position and resize other children here
}

You probably also want to include the background skin with the measurement calculations inside the autoSizeIfNeeded() function:

var newWidth:Number = this.explicitWidth;
if(needsWidth)
{
    newWidth = this._label.width + 2 * this._padding;
    var backgroundWidth:Number = this._backgroundSkin.width;
    if(backgroundWidth > newWidth)
    {
        newWidth = backgroundWidth;
    }
}
var newHeight:Number = this.explicitHeight;
if(needsHeight)
{
    newHeight = this._label.height + 2 * this._padding;
    var backgroundHeight:Number = this._backgroundSkin.height;
    if(backgroundHeight > newWidth)
    {
        newWidth = backgroundHeight;
    }
}

Instead of always using the current dimensions of the background skin for measurement, we could save the dimensions of the background skin in member variables when the backgroundSkin setter is called. Let's say that we call the variables originalBackgroundSkinWidth and originalBackgroundSkinHeight. This will allow us to always measure using the original dimensions of the background skin instead of basing the measurement on the this._backgroundSkin.width and this._backgroundSkin.height values that may get changed in layoutChildren().

Multiple background skins

The example code above adds only a single background skin. What if you want to display a different background skin for each touch phase?