Adobe
Products
Acrobat
Creative Cloud
Creative Suite
Digital Marketing Suite
Digital Publishing Suite
Elements
Photoshop
Touch Apps
Student and Teacher Editions
More products
Solutions
Creative tools for business
Digital marketing
Digital media
Education
Financial services
Government
Web Experience Management
More solutions
Learning Help Downloads Company
Buy
Home use for personal and home office
Education for students, educators, and staff
Business for small and medium businesses
Licensing programs for businesses, schools, and government
Special offers
Search
 
Info Sign in
Welcome,
My cart
My orders My Adobe
My Adobe
My orders
My information
My preferences
My products and services
Sign out
Why sign in? Sign in to manage your account and access trial downloads, product extensions, community areas, and more.
Adobe
Products Sections Buy   Search  
Solutions Company
Help Learning
Sign in Sign out My orders My Adobe
Preorder Estimated Availability Date. Your credit card will not be charged until the product is shipped. Estimated availability date is subject to change. Preorder Estimated Availability Date. Your credit card will not be charged until the product is ready to download. Estimated availability date is subject to change.
Qty:
Purchase requires verification of academic eligibility
Subtotal
Review and Checkout
Adobe Developer Connection / Flash Developer Center /

Creating ActionScript 3.0 components in Flash – Part 7: Focus management

by Jeff Kamerer

Jeff Kamerer

Created

9 June 2008

Page tools

Share on Facebook
Share on Twitter
Share on LinkedIn
Bookmark
Print
ActionScript best practice components Flash Professional keyboard

Requirements

Prerequisite knowledge

To get the most from this article series, you should be familiar with Flash Professional, including how to manipulate the Timeline, the Property inspector, the Components panel, the Components inspector, the Library, and the Actions panel.

User level

Beginning

Required products

  • Flash Professional (Download trial)

Sample files for Part 7

  • component_focus_management.zip (665 KB)

In this part of the article series on creating components using ActionScript 3.0, I discuss how to control focus in the MenuBar component. If you skipped the articles leading up to this section of the series, you might find it helpful to review the previous sections. In Part 1 you can download the sample files for the entire series of articles all at once. Or if you prefer to just follow along with Part 7, you can download the sample files for this part of the series below.

For your reference, here are all the parts in this series:

  • Part 1: Introducing components
  • Part 2: MenuBar component prototype
  • Part 3: From prototype to component
  • Part 4: Events
  • Part 5: Styles and skins
  • Part 6: Invalidation model
  • Part 7: Focus management
  • Part 8: Keyboard support
  • Part 9: Shim compiled clip

Before I begin discussing how to support and control focus in the MenuBar component, let's take a look at our progress so far and see why this is important. If you've been following along with this article series, you'll remember that we added invalidation to our test.fla file. Since we've made many changes to the project, now is a good time to try Control > Test Movie to evaluate the way the menu bar is working.

As you test the movie, make sure that the option to Disable Keyboard Shortcuts is checked under the Control menu, then start hitting the Tab key to change the focus. As you navigate through the top level of menu items, it will look as though everything is working at first. But now try clicking on the MenuBar to open one of the drop-down menus and hit the Tab key several more times. You'll see the focus going to the TileList for the menu bar and then to the List for the drop-down menu separately, which is not the desired behavior.

After making some tests, we've diagnosed the issue: the subcomponents are getting focus but the MenuBar component is not. In this article, we'll discover how to resolve this, and how to control focus events using the FocusManger.

Controlling and debugging focus issues using FocusManager

In order to ensure that our MenuBar component functions as users would expect it to, it's necessary to add focus support via ActionScript. Not only is this important for creating intuitive interactions with users – but it is also critical for ensuring that the drop-down menus will be accessible to specially-abled users who rely on using the keyboard, rather than the mouse, to select items in MenuBar component's drop-down menus.

IFocusManagerComponent

Communicating to the User Interface Component Infrastructure that your component wants focus is very easy. Any class that can have focus needs to implement the interface fl.managers.IFocusManagerComponent. The changes to the ActionScript to support this in MenuBar were very straightforward.

Here's the code I used to achieve this:

import fl.managers.IFocusManagerComponent; public class MenuBar extends UIComponent implements IFocusManagerComponent {

All of the classes for components implement this interface. Classes that are for display objects that are only used within components, like fl.controls.listClasses.CellRenderer, do not.

Implementing IFocusManagerComponent registers a component with the FocusManager, which is implemented by fl.managers.FocusManager, as a component that wants focus. If a display object does not inherit from UIComponent, then the FocusManager treats it using the normal rules for display objects. Buttons and movie clips do not have to do anything special to get the focus.

focusEnabled

Implementing IFocusManagerComponent is all that is necessary to get focus working for a component that does not have any subcomponents. However, in our sample project the MenuBar component has components within it that also require focus. You can easily disable focus by setting the focusEnabled property to false. In MenuBar, I changed configUI() to set the focusEnabled property on myMenuBar. I also changed createMenu() to customize the drop-down menus, as shown in the code below:

override protected function configUI():void { // always call super.configUI() in your implementation super.configUI(); // dynamically create myMenuBar myMenuBar = new MenuBarTileList(); // keeps TileList from accepting focus, must be done before addChild myMenuBar.focusEnabled = false; // turning off selectable makes the TileList instance behave more like a menu bar myMenuBar.selectable = false; // need to listen for a mouseDown event on the menu bar TileList // to start the menu handling. Other mouse event handlers will // be added after the initial mouseDown on the TileList menu bar // and removed when the menus are closed. myMenuBar.addEventListener(MouseEvent.MOUSE_DOWN, menuBarMouseHandler); // finally, add myMenuBar addChild(myMenuBar); } private function createMenu():List { var theMenu:List = new MenuList(); theMenu.visible = false; theMenu.selectable = false; // keeps TileList from accepting focus theMenu.focusEnabled = false; myMenus.push(theMenu); addChildAt(theMenu, 0); return theMenu; }

The order of operations is very important here. The focusEnabled property must be set immediately after the component instances are created and before they are added to the display list. If you want to turn off focus for a component instance that is not dynamically created, then after setting the focusEnabled property you'll need to remove the object from the display list and add it again, like this:

myButton.focusEnabled = false; removeChild(myButton); addChild(myButton);

Debugging focus problems

Initially I had some difficulties making this change to the code, because originally I had set focusEnabled after calling addChild() for myMenuBar. This caused the tab focus to stall on the MenuBar instance. After doing some troubleshooting and testing, I eventually discovered this was because myMenuBar was in the FocusManager's list for focusable display objects, right after my MenuBar instance. When I hit the Tab key, the focus would try to shift to myMenuBar, but it would fail since focusEnabled was set to false.

The first thing I did as I was debugging this issue was to add stage listeners for the focus events. Stage listeners can be a very helpful tool to help you identify where focus events, keyboard events, and mouse events are going. The event's currentTarget property will always be the Stage, but the target property will indicate who received the event. To facilitate debugging, I temporarily added the following code to the frame script in test.fla:

stage.addEventListener(FocusEvent.FOCUS_IN, focusInHandler); function focusInHandler(e:FocusEvent):void { trace("focus into " + e.target); } stage.addEventListener(FocusEvent.FOCUS_OUT, focusOutHandler); function focusOutHandler(e:FocusEvent):void { trace("focus out of " + e.target); } stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler); function keyDownHandler(e:KeyboardEvent):void { trace("key down to " + e.target); }

The traces output from these listeners all seemed normal, except I realized that once focus hit the MenuBar component, it never received another focusIn or focusOut event.

My next step in this process was to use the debugger. I added the User Interface Component source to the classpath of test.fla and set some break points in FocusManager. After experimenting with adding break points in different methods, I had luck with a break point I added in keyFocusChangeHandler(). I stepped through the code into setFocusToNextObject() and from there into getNextFocusManagerComponent(), and it was while stepping through that method that I realized the focusableCandidates array had a MenuBarTileList instance in it, which was wrong. This made me realize that something must be going wrong when I set focusEnabled on the MenuBar component instance—which led me to consider whether the timing of the call was at the root of the problem.

In the next section of this article, we'll take a look at the steps I took to fix the focus issues.

Resolving focus event display issues

At this point, the menu was almost working as expected but I needed to make just a few more changes to the code in order to resolve issues with the way the drop-down menus were behaving. By adding some code to handle the focus events and control the order of display objects, I was able to make the MenuBar component retain the focus and work in an intuitive way.

Handling focusOut

Focus was now tabbing in and out of the MenuBar component correctly, and the simple steps I had taken thus far would be enough for many components that you may develop. But the MenuBar component contains subcomponents. If I had a drop-down menu showing and I hit the tab key to move focus to the next component, the drop-down menu remained open. To fix this issue, I added code to handle the focusOut event.

If your component needs to handle either the focusIn or focusOut event, you do not need to add your own listener because UIComponent registers focusInHandler() and focusOutHandler() and you can override these methods. The UIComponent implementations handle drawing the focusRectSkin, so you should always call the super implementation.

For MenuBar, I overrode focusOutHandler() to close any open menus, as shown in the code example below:

override protected function focusOutHandler(e:FocusEvent):void { closeMenuBar(); super.focusOutHandler(e); }

Customizing drawFocus

When the focusRectSkin was drawn around the MenuBar component and a drop-down menu was open, the drop-down menu would cover the focusRectSkin. I did not like that behavior. Fortunately, I discovered I could change it by overriding drawFocus() and adding a few lines of code. I found this by reading the ActionScript source and by stepping through each line of code in the debugger.

You will find there are many places you can tweak the behavior of the User Interface Component Infrastructure this way, but documenting them all is outside the scope of this article series. As you develop components, you will find that you'll need to do some research and analyze the code to determine the best way to update it.

The UIComponent implementation of drawFocus() adds the focusRectSkin at the bottom of the display list, so at this point I just needed to move it to the top.

Check out the code below to see how this was accomplished:

override public function drawFocus(focused:Boolean):void { super.drawFocus(focused); if (focused && uiFocusRect != null) { setChildIndex(uiFocusRect, numChildren - 1); } }

Where to go from here

In Part 8 you'll add keyboard support to the MenuBar component so that users can navigate through the drop-down menus using key presses (up and down arrows, the Spacebar, the Escape or Return keys) to make the menu bar easier to negotiate and more accessible.

If this article has made you curious about working with focus events and you'd like to learn more about how to control them with ActionScript 3.0, be sure to check out the ActionScript 3.0 Language and Components Reference sections that are listed below:

  • ActionScript 3.0 documentation on FocusManager
  • ActionScript 3.0 documentation on IFocusManager
  • ActionScript 3.0 documentation on IFocusManagerComponent

More Like This

  • Controlling web video with ActionScript 3 FLVPlayback programming
  • Controlling the appearance of text elements with the Text Layout Framework
  • Optimizing content for Apple iOS devices
  • Creating ActionScript 3.0 components in Flash – Part 6: Invalidation model
  • Creating ActionScript 3.0 components in Flash – Part 8: Keyboard support
  • Creating ActionScript 3.0 components in Flash – Part 9: Shim compiled clip
  • Modeling User Workflows for Rich Internet Applications
  • Common mistakes working with fonts and text objects in Flash
  • Avoiding common Timeline errors in Flash
  • Using timeline labels to dispatch events with the ActionScript 3.0 TimelineWatcher class

Flash User Forum

More
04/23/2012 Auto-Save and Auto-Recovery
04/23/2012 Open hyperlinks in new window/tab/pop-up ?
04/21/2012 PNG transparencies glitched
04/01/2010 Workaround for JSFL shape selection bug?

Flash Cookbooks

More
02/13/2012 Randomize an array
02/11/2012 How to create a Facebook fan page with Flash
02/08/2012 Digital Clock
01/18/2012 Recording webcam video & audio in a flv file on local drive

Products

  • Acrobat
  • Creative Cloud
  • Creative Suite
  • Digital Marketing Suite
  • Digital Publishing Suite
  • Elements
  • Mobile Apps
  • Photoshop
  • Touch Apps
  • Student and Teacher Editions

Solutions

  • Digital marketing
  • Digital media
  • Web Experience Management

Industries

  • Education
  • Financial services
  • Government

Help

  • Product help centers
  • Orders and returns
  • Downloading and installing
  • My Adobe

Learning

  • Adobe Developer Connection
  • Adobe TV
  • Training and certification
  • Forums
  • Design Center

Ways to buy

  • For personal and home office
  • For students, educators, and staff
  • For small and medium businesses
  • For businesses, schools, and government
  • Special offers

Downloads

  • Adobe Reader
  • Adobe Flash Player
  • Adobe AIR
  • Adobe Shockwave Player

Company

  • News room
  • Partner programs
  • Corporate social responsibility
  • Career opportunities
  • Investor Relations
  • Events
  • Legal
  • Security
  • Contact Adobe
Choose your region United States (Change)
Choose your region Close

North America

Europe, Middle East and Africa

Asia Pacific

  • Canada - English
  • Canada - Français
  • Latinoamérica
  • México
  • United States

South America

  • Brasil
  • Africa - English
  • Österreich - Deutsch
  • Belgium - English
  • Belgique - Français
  • België - Nederlands
  • България
  • Hrvatska
  • Česká republika
  • Danmark
  • Eastern Europe - English
  • Eesti
  • Suomi
  • France
  • Deutschland
  • Magyarország
  • Ireland
  • Israel - English
  • ישראל - עברית
  • Italia
  • Latvija
  • Lietuva
  • Luxembourg - Deutsch
  • Luxembourg - English
  • Luxembourg - Français
  • الشرق الأوسط وشمال أفريقيا - اللغة العربية
  • Middle East and North Africa - English
  • Moyen-Orient et Afrique du Nord - Français
  • Nederland
  • Norge
  • Polska
  • Portugal
  • România
  • Россия
  • Srbija
  • Slovensko
  • Slovenija
  • España
  • Sverige
  • Schweiz - Deutsch
  • Suisse - Français
  • Svizzera - Italiano
  • Türkiye
  • Україна
  • United Kingdom
  • Australia
  • 中国
  • 中國香港特別行政區
  • Hong Kong S.A.R. of China
  • India - English
  • 日本
  • 한국
  • New Zealand
  • 台灣

Southeast Asia

  • Includes Indonesia, Malaysia, Philippines, Singapore, Thailand, and Vietnam - English

Copyright © 2012 Adobe Systems Incorporated. All rights reserved.

Terms of Use | Privacy Policy and Cookies (Updated)

Ad Choices

Reviewed by TRUSTe: site privacy statement