How to use the Feathers DefaultListItemRenderer
and DefaultGroupedListItemRenderer
The DefaultListItemRenderer
and DefaultGroupedListItemRenderer
classes provide a basic way to display items from data collections in the List
and GroupedList
components. These default item renderers are derived from the same base class, and their functionality is virtually identical.
In many of the examples below, code and descriptions will refer to the DefaultListItemRenderer
class and the IListItemRenderer
interface, which are both used by the List
component. When using a GroupedList
component, you should substitute the DefaultGroupedListItemRenderer
class and the IGroupedListItemRenderer
instead.
These item renderer types for GroupedList
will have all of the same properties that are used in the examples below. The differences between the List
and GroupedList
versions of item renderers are entirely behind the scenes.
The Basics
Item renderers are managed by a List
or GroupedList
component, and you generally don't add them to the display list directly. To customize properties on a default item renderer, you can use the list's itemRendererFactory
:
list.itemRendererFactory = function():IListItemRenderer
{
var renderer:DefaultListItemRenderer = new DefaultListItemRenderer();
renderer.labelField = "text";
return renderer;
}
In the next section, we'll look at several examples of properties that we can set in the itemRendererFactory
.
Children of a default item renderer
An item renderer provides up to three children to display data. A label, an icon, and an accessory. A label must always display a string in a text renderer. However, both the icon and the accessory have three different ways to display data. They may display either a texture or URL in an ImageLoader
, a string in a text renderer, or they can add an arbitrary display object, like a Feathers component, as a child.
Label
The labelField
property displays a string in the primary text renderer.
Consider the following item in a data provider:
{ text: "Example Item" }
For an item renderer to display "Example Item" string, it needs to know about the item's text
property:
renderer.labelField = "text";
The default item renderer also has a labelFunction
property that may be used to generate a string dynamically.
Icon
The icon is typically intended for displaying a texture (either preloaded or from a URL) in an ImageLoader
component. However, for convenience, it may also display a string in another text renderer, or it may add any Starling display object as a child.
When loading a texture or URL, the item renderer will create and manage its own internal ImageLoader
instance. If the texture is loaded from a URL, we do not need to dispose this texture when we are finished with it. The texture will be disposed when the ImageLoader
is disposed. If we pass in a preloaded texture, it is our responsibility to dispose it when needed.
To display a texture or a URL, you may use the iconSourceField
property.
Consider the following item from the data provider:
{ label: "Example Label", thumbnail: atlas.getTexture( "texture-name" ) }
For an item renderer to display the texture from the altas, it needs to know about the item's thumbnail
property:
renderer.iconSourceField = "thumbnail";
Similar to the labelField
property, the iconLabelField
property can be used to display a string in another text renderer. This can be a convenient way to display another line of text, or it could even be used to display symbols using icon fonts.
Finally, if you need to display a Feathers component or any other type of Starling display object, you can use the iconField
property.
Consider the following code where a Slider
component is included in a list's data provider:
var slider:Slider = new Slider();
slider.minimum = 0;
slider.maximum = 10;
slider.step = 1;
slider.value = 0;
list.dataProvider = new ListCollection(
[
{ label: "Example Label", control: slider }
];
For an item renderer to add the display object as a child, it needs to know about the item's control
property:
renderer.iconField = "control";
When using iconField
, it's important to understand that the display object in the data provider will not be automatically disposed when the item renderer or the list is disposed. This display object may need to be used in another list later, and Feathers cannot know whether it is safe to dispose it, similar to how a starling.display.Image
cannot dispose its starling.textures.Texture
. To avoid memory leaks, remember to dispose any display objects included in the list's data provider when the list is disposed. The dispose()
function on the data provider makes it easy to dispose display objects in the ListCollection
.
Accessory
In addition to the label and the icon, the default item renderer can display a third child, an accessory. This is a display object that is added as a child and it is often meant to be interactive in some way. For instance, you might create a list of settings with labels on the left and some user interface controls like sliders and toggle switches on the right.
When using interactive accessories, it's a good idea to set the list's isSelectable
property to false
to avoid touch conflicts and user confusion. When a list displays interactive accessories, it may not be obvious that the items in a list may be touched to select them too.
Similar to icons, for extra convenience and flexibility, an accessory may be a text renderer that displays a string, an ImageLoader
that displays a texture, or a Starling display object that is added as a child. You may use the accessorySourceField
property, the accessoryLabelField
property, and the accessoryField
property. These properties work the same as they would for icons.
Similar to iconField
, a display object in the list's data provider that is displayed using accessoryField
will not be automatically disposed when the item renderer or the list is disposed. See the note above about iconField
for details.
Skinning a default item renderer
The DefaultListItemRenderer
class is a subclass of the ToggleButton
component. Like a button, the default item renderer can change its background skin based on the touch state, and it supports different background skins when selected too. Similarly, an item renderer may have both a label and an icon, and all of the layout options used by buttons for alignment, gap, and padding apply to an item renderer too. For full details about these style properties, see How to use the Feathers Button
component and How to use the Feathers ToggleButton
component. For the full listing of all style properties available on the default item renderers, see the DefaultListItemRenderer
API reference.
Next, we'll look at a few of the common properties that the default item renderers add beyond what normal button's provide.
Layout with an accessory
Buttons may have two children, a label text renderer and an icon, but the default item renderers add a third child, known as an accessory. Earlier, we looked at how an accessory may be passed in through the data provider. Now, let's look at some of the layout options available when adding an accessory into the mix.
Positioning the accessory in the item renderer's layout is very similar to positioning the icon relative to the label text renderer. The default item renderer has an accessoryPosition
property that will allow it to be positioned relative to the other children. The accessoryGap
property defines the gap in pixels between the accessory and the other children.
When displaying all three children that the default item renderer supports (the label text renderer, the icon, and the accessory), you can use the layoutOrder
property to customize the order that the children are positioned in the layout. By default, the label text renderer is positioned first, followed by the icon (relative to the label), and finally, the accessory is positioned last (relative to the combined bounding box of the label and the icon). Alternatively, you can change the order so that the label text renderer is positioned first, followed by the accessory (relative to the label), and the icon is positioned last (relative to the combined bounding box of the label and the accessory).
Targeting a default item renderer in a theme
If you are creating a theme, you can specify a function for the default styles like this:
getStyleProviderForClass( DefaultListItemRenderer ).defaultStyleFunction = setItemRendererStyles;
If you want to customize a specific item renderer to look different than the default, you may use a custom style name to call a different function:
list.customItemRendererStyleName = "custom-item-renderer";
You can set the function for the custom style name like this:
getStyleProviderForClass( DefaultListItemRenderer )
.setFunctionForStyleName( "custom-item-renderer", customItemRendererInitializer );
Trying to change the item renderer's styles and skins outside of the theme may result in the theme overriding the properties, if you set them before the item renderer was added to the stage and initialized. Learn to extend an existing theme to add custom skins.
Of you aren't using a theme, then you may set the item renderer's properties through the List's itemRendererFactory
or itemRendererProperties
.