Create a ToggleButton Menu / Bar in Flex 4
In Flex 4 you have the ability to use the mx components or the new spark components. I started a project the other day and wanted to use a ToggleButtonBar and noticed the only on available was the mx component. Spark does come with a toggle button but it is a single button. Also I wanted to be able to use the ToggleButtonBar as a vertical menu and the mx component, to my knowledge, only lays out horizontally, and extending that component to get it to layout vertical just seemed like to much of a pain.
After thinking about the issue for a moment I dove right in and here is the resulting code that I came up with.
package com.mswallace.components.menus
{
import flash.events.FocusEvent;
import flash.events.KeyboardEvent;
import flash.events.MouseEvent;
import mx.collections.ArrayCollection;
import mx.collections.ArrayList;
import mx.events.FlexEvent;
import spark.components.Group;
import spark.components.ToggleButton;
public class ToggleMenu extends Group
{
public function ToggleMenu()
{
super();
this.addEventListener(FlexEvent.CREATION_COMPLETE, onCreationComplete);
}
private function onCreationComplete(event:FlexEvent):void
{
this.addEventListener(FocusEvent.FOCUS_IN, onFocusIn);
}
private function onFocusIn(event:FocusEvent):void
{
this.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
}
private function onKeyDown(event:KeyboardEvent):void
{
trace(event.keyCode);
}
private function createMenu():void
{
if(this.numChildren > 0)
this.removeAllElements();
for (var i:String in toggleButtons)
{
var value:String = toggleButtons.getItemAt(int(i)) as String;
var toggleButton:ToggleButton = new ToggleButton();
toggleButton.label = value;
toggleButton.id = 'bn_' + value;
toggleButton.addEventListener(MouseEvent.CLICK, onClick);
this.addElement(toggleButton);
}
//this is optional code to select the first item
}
private function onClick(event:MouseEvent):void
{
if(event.currentTarget.selected == false)
{
event.currentTarget.selected = true;
selectedIndex = this.getChildIndex(event.currentTarget as ToggleButton);
}
for(var i:int=0; i< this.numChildren; ++i )
{
var button:ToggleButton = this.getElementAt(i) as ToggleButton;
if(event.currentTarget != button)
button.selected = false;
}
}
///////// vars \\\\\\\\\\\\
//array of string values that is passed in to create the buttons
private var _toggleButtons : ArrayCollection;
public function get toggleButtons():ArrayCollection
{
return _toggleButtons;
}
public function set toggleButtons( value : ArrayCollection ):void
{
_toggleButtons = value;
if(value != null && value.length > 0)
createMenu();
}
//selected index
private var _selectedIndex:int;
public function get selectedIndex():int
{
return _selectedIndex;
}
public function set selectedIndex(value:int):void
{
_selectedIndex = value;
}
}
}Here is the component implemented in MXML after creating the Actionscript Class.
I only did this so that I could control the layout in mxml tags but you could also implement the layout in the Actionscript class if you like.
I only did this so that I could control the layout in mxml tags but you could also implement the layout in the Actionscript class if you like.
I tend to follow a "code behind" method when creating some of my components.
<?xml version="1.0" encoding="utf-8"?>
<menus:ToggleMenu
xmlns:menus="com.mswallace.components.menus.*"
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx">
<menus:layout>
<s:VerticalLayout />
</menus:layout>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
</menus:ToggleMenu>