Flex "RadioButton" ListItemRenderer
Posted by Joe Rinehart at 2:44 PM
6 comments - Categories:
Flex
I'm becoming an ever increasing fan of the way the Flex visual components were built. Yeah, some things are private when protected would be nice, but for the kind of data-focused work I do I find myself rarely getting stuck. On top of that, building Flex widgets is the perfect 3:00AM brain exercise for when our 3 month old daughter wakes me up.
Anyhow, I needed a better way to show long lists of radio buttons in a UI. Using a repeater just kind of stank - I wanted something that worked like a normal list, but showed a RadioButton beside each item. Thirty minutes later, I was in business:

I decided to blog it as it's a dead simple example of how to extend a base Flex component, add additional visual children, and control both the layout and data-focused aspects through the UIComponent "lifecycle" methods and Flex events.
Here's the code for the renderer:
{
import mx.controls.RadioButton;
import mx.controls.listClasses.BaseListData;
import mx.controls.listClasses.ListBase;
import mx.controls.listClasses.ListItemRenderer;
import mx.events.ListEvent;
public class RadioButtonListItemRenderer extends ListItemRenderer
{
/**
* Radio button shown at left of control.
*/
private var radioButton:RadioButton;
/**
* List owning this renderer.
*/
private var list:ListBase;
/**
* Override createChildren() to create a radio button.
*/
override protected function createChildren():void
{
super.createChildren();
// Create our radio button and add it to the display list.
this.radioButton = new RadioButton();
this.addChild(this.radioButton);
}
/**
* Override updateDisplayList to position radio button
* and shift label.
*/
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
{
// Shift what super thinks of width by our radio's width...
super.updateDisplayList(unscaledWidth - this.radioButton.width, unscaledHeight);
// For my purposes, a hard width is fine.
this.radioButton.width = 25;
// Place our radio
this.radioButton.x = 6;
this.radioButton.y = this.height / 2 - this.radioButton.height / 2;
// Slide that label over
this.label.x = this.radioButton.width;
}
/**
* Override the listData setter to add listener for changes to the owner (List selection change)
*/
override public function set listData(value:BaseListData):void
{
super.listData = value;
// If we're in the right condition
if (value.owner is ListBase)
{
// Remove event listeners from any prior assigned list
if (this.list)
{
this.list.removeEventListener(ListEvent.CHANGE, ownerChangeHandler);
}
// Keep the list around
this.list = value.owner as ListBase;
// Watch the list for changes to its selection
this.list.addEventListener(ListEvent.CHANGE, ownerChangeHandler, false, 0, true);
}
}
/**
* When the list's selection changes, update the state of the radio button.
*/
private function ownerChangeHandler(event:ListEvent):void
{
// If the list has a selection and it's this renderer's data, check the button
this.radioButton.selected = (this.data != null && this.data == this.list.selectedItem);
}
}
}
Enjoy, and happy listing!
Hussein Grant wrote on 08/14/08 2:15 PM
Hi Joe,I am now getting into flex heavy and was wondering, where exactly did you find thorough documentation on all those overridable functions? Without this knowledge it's really hard to do certain things yourself and with a certain level of confidence.
Otherwise good mind teaser. I am hungry for flex lately.
Thanks,
Hussein