Flash: 4 Tricks for using MovieClips as Buttons

by troy on March 13, 2008

So here are 4 tricks I've found useful:

  1. Use actionscript to create the Button behavior (enlarging etc), centralizing it in one place.
  2. Use clips styled in the IDE, and copy their style/filters for mouse over, down, disabled state.
  3. Use mouseEnabled (and alpha/brightness) to temporarily disable a button
  4. Use the instance name as the label, and in the event parsing.

(Either JavaScript is not active or you are using an old version of Adobe Flash Player. Please install the newest Flash Player.)

Styling MOUSE_OVER, MOUSE_DOWN States

Similar to CSS centralizing style, centralizing behavioral style offers the same maintenance advantages.   Using clips on the stage for style allows the designer to visually see what's desired, rather than spending countless iterations tweaking actionscript to get it right, it's a good handoff in team based approach.   I also sometimes use describeType 'autowire' any buttons of particular classes.   For the disabled state I stacked two brightness filters ontop of each other.

Styling it to send all the events to a central controller (MVC UCM style), allows things to be debugged far easier than when events are going everywhere, and the controller has internal state, respond appropriately, say ignoring all clicks during loading, without having to rewire all the various components.

For 1 and 2 here's the underlying code. Notice I use mouseChildren = false to keep the label textfield from generating events.

function configureMC_Button(ary:Array, addL:Boolean = true):void {var a:MovieClip; 
 
var i:int = 0; 
 
var n:int =ary.length; 
 
for (true; i < n; ++i) { 
 
a = ary[i]; 
 
if (addL) { 
 
a.addEventListener(MouseEvent.MOUSE_OVER, onMouseOverHandler); 
 
a.addEventListener(MouseEvent.MOUSE_OUT, onMouseOutHandler); 
 
a.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDownHandler); 
 
a.addEventListener(MouseEvent.MOUSE_UP, onMouseOverHandler);a.addEventListener(MouseEvent.CLICK, onMouseClickHandler); 
 
a.mouseChildren =false; 
 
} else { 
 
a.removeEventListener(MouseEvent.MOUSE_OVER, onMouseOverHandler); 
 
a.removeEventListener(MouseEvent.MOUSE_OUT, onMouseOutHandler); 
 
a.removeEventListener(MouseEvent.MOUSE_DOWN, onMouseDownHandler); 
 
a.removeEventListener(MouseEvent.MOUSE_UP, onMouseOverHandler); 
 
a.removeEventListener(MouseEvent.CLICK, onMouseClickHandler); 
 
} 
 
} 
 
} 
 
function onMouseClickHandler(evt:Event):void { 
 
var mc:MovieClip = MovieClip(evt.target); 
 
output_txt.text =(" \r"+ mc.label_txt.text + "**Clicked **"); 
 
} 
 
function onMouseDownHandler(evt:Event):void { 
 
var mc:MovieClip = MovieClip(evt.target); 
 
mc.filters = downTreatment.filters; 
 
} 
 
function onMouseOverHandler(evt:Event):void { 
 
var mc:MovieClip = MovieClip(evt.target); 
 
mc.scaleX = mc.scaleY = 1.2; 
 
mc.filters = overTreatment.filters; 
 
} 
 
function onMouseOutHandler(evt:Event):void { 
 
var mc:MovieClip = MovieClip(evt.target); 
 
mc.scaleX = mc.scaleY = 1; 
 
mc.filters = []; 
 
} 
 
overTreatment.visible = downTreatment.visible = disabledTreatment.visible = false; 
 
configureMC_Button([a_btn, b_btn, c_btn, d_btn, e_btn, f_btn, g_btn]);

Enabling and Disabling via ActionScript

You can disable/enable a clip simply by using the mouseEnabled field which will turn on or off mouse events.   Contrast this with the approach of adding/removing listeners to enable or disable a button, which may have multiple listeners for different classes, you can't see, so you never know if you got them all.

function setEnabled(  ary:Array, enable:Boolean = true):void {var a:MovieClip; 
 
var i:int = 0; 
 
var n:int =ary.length; 
 
for (true; i < n; ++i) { 
 
a = ary[i]; 
 
if (enable) { 
 
a.mouseEnabled = false; 
 
a.filters =[]; 
 
} else { 
 
a.mouseEnabled = false; 
 
a.filters = disabledTreatment.filters; 
 
} 
 
} 
 
} 
 
setEnabled([d_btn, e_btn], false);

Using the instance name as id.

Using the instance as the basis for identification, saying parsing it for use the label, and in the event, can make things more uniform than having buttons dispatching events,.   In internationalized apps where the label changes based on whatever language is present, the instance name can serve as a key to finding the appropriate text in some multilanguage dictionary, or even show when a label is missing.

In Closing
Using a single movieClip has many advantages,  only one skin has to be created instead of 4-5 for a SimpleButton.   When handled in the way outlined above it has many of the advantages of being a component, without the work of being a full blown one.   It minimizes the number of classes/library items when each button is created with a unique label hard coded into it.

In conjunction with a tweening engine, it allows for what I call momentum styled buttons.   Buttons that don't have crisp state changes like SimpleButton attempts on the mouse up/over/down. Things that fade up, and down, like real world lightbulbs, cars.   When used with ColorTransform this can allow for adaptively styled UI, like that of CSS.

There are also safety benefits. In AS3.0 the timeline is purely script driven, there are still bugs when using multiple frames to manage state on particular versions of the flash player.   I've had odd issues with sound not firing or not stopping firing, components blowing up when in tweens or in timelines.

Leave a Comment

Previous post:

Next post: