- Print
- DarkLight
Overview
To allow this to work, you must manually enable focus on the UI elements you wish to be reached by navigation. You must also control the focus order. These are accomplished using standard Android mechanisms that are summarized here for convenience.
Making UI Elements Focusable
The easiest way to make the UI easily navigated with the buttons and touchpad is to explicitly define the focus rules in the layout XML.
All UI elements including layouts should explicitly define android:focusable and android:focusableInTouchMode
<Button
android:id="@+id/firstButton"
android:focusable="true"
android:focusableInTouchMode="true"
android:text="Sample Button"
/>
If these are set true, the system will allow them to become focused. If you have an element, such as a layout or textview, that should never become focused, explicitly set them to false.
Default Focus
The system will give focus to a UI element when the activity starts. To make your application predictable and consistent, you should explicitly request a single UI element request the default focus. You can do this in the layout XML, or in java code.
Default Focus in XML Layout
To request focus in XML we need to add the empty XML element "requestFocus" nested within one of the UI elements.
Most of the layout is controlled by XML attributes and developers normally use self-closing tags. To modify an element to request focus you will need to explicitly add an end tag, and nest the requestFocus within it. The button example below is modified to request focus as:
<Button
android:id="@+id/firstButton"
android:focusable="true"
android:focusableInTouchMode="true"
android:text="Sample Button"
>
<!-- Notice the Button element that requests focus is not self-closing so it can contain an element -->
<requestFocus />
</Button>
Default Focus in Java Code
You can also easily request focus of any UI element in your onCreate() method.
@Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button sampleButton = (Button) findViewById(R.id.firstButton);
// It is a best practice to explicitly request focus to a specific UI
// element to make navigation with the buttons more consistent to the
user
sampleButton.requestFocusFromTouch();
}
This makes the request to grab the focus as soon as the Activity is created.
Controlling Focus Order
Since the buttons are used to change focus between items, you may want to explicitly control the focus order. There are two ways to do this. You can specify this in the XML, or you can use java code.
Controlling Focus Order in the Layout XML
The XML attributes can define the focus order used to highlight buttons and views within the screen.
The navigation buttons send left and right, so set the android:nextFocusLeft and android:nextFocusRight to valid elements.
<Button
android:id="@+id/firstButton"
android:focusable="true"
android:focusableInTouchMode="true"
android:nextFocusLeft="@+id/thirdButton"
android:nextFocusRight="@+id/secondButton"
android:text="Sample Button"
/>
<Button android:id="@+id/secondButton"
android:focusable="true"
android:focusableInTouchMode="true"
android:nextFocusLeft="@+id/firstButton"
android:nextFocusRight="@+id/thirdButton"
android:text="Second Button"
/>
<Button android:id="@+id/thirdButton"
android:focusable="true"
android:focusableInTouchMode="true"
android:nextFocusLeft="@+id/secondButton"
android:nextFocusRight="@+id/firstButton"
android:text="Third Button"
/>
This example creates circular behavior where you can go to the right or left around all the buttons. Going right from the thirdButton returns to the firstButton. The opposite direction works as well.
You can also make a dead-end so you do not circle around by having elements point to themselves as the next focus. This is the same example without wrapping:
<Button android:id="@+id/firstButton"
android:focusable="true"
android:focusableInTouchMode="true"
android:nextFocusLeft="@+id/firstButton"
android:nextFocusRight="@+id/secondButton"
android:text="Sample Button"
/>
<Button android:id="@+id/secondButton"
android:focusable="true"
android:focusableInTouchMode="true"
android:nextFocusLeft="@+id/firstButton"
android:nextFocusRight="@+id/thirdButton"
android:text="Second Button"
/>
<Button android:id="@+id/thirdButton"
android:focusable="true"
android:focusableInTouchMode="true"
android:nextFocusLeft="@+id/secondButton"
android:nextFocusRight="@+id/thirdButton"
android:text="Third Button"
/>
In this case, going left from firstButton stays on firstButton. Going right from thirdButton stays on thirdButton.
Combining these gives you complete control over the behavior of the buttons entirely within the XML. The downside to this is it is quite cumbersome to insert new UI elements.
Controlling Focus Order in Java
To override the order in which UI components receive focus, you can override ViewGroup.focusSearch(View focused, int direction). This method takes two parameters, the current view that has focus and the direction in which to move focus to. You can implement whatever rules you want to return a specific view that will receive focus next based on the current focus and direction. As a fallback, you should always return super.focusSearch(focused, direction) if you choose not to return a specific view.
Downloadable Sample
A sample project for Android Studio can be downloaded here.
Summary
By explicitly setting each UI element to be focusable or not, defining a default item to have focus, and controlling the focus order, the developer can create a highly usable interface to work with the physical buttons or the touchpad.