What you should know about Android Touch Mode and Focus

  • Written by  Clive

Get in touch and stay in focus

Android Touch Mode and focus icon

So what’s Touch Mode?

Users can interact with their Smart Android devices using hardware keypads and buttons or by touching the screen.

Touching the screen puts the device into touch mode. The user can then interact with it by touching the on-screen virtual buttons, images, etc.

The device remains in touch mode across activities until the user exits touch mode.

Touching a hardware button causes the device to exit touch mode.

You can check if the device is in touch mode by calling the View class’s isInTouchMode()  method.

So what’s focus?

A view or widget is usually highlighted or displays a flashing cursor when it’s in focus. This indicates that it’s ready to accept input from the user.

Focus is necessary for devices using trackballs, styluses, external keyboards and hardware buttons so that the user can see which view is ready to receive input.

Focus is not necessary when the device is in touch mode.

Handling focus

The system predicts which views should be in focus. It changes focus depending on the user’s input and as views are removed or displayed.

Setting the focus

It’s a good idea to make sure that all of the views that the user should be able to navigate to are focusable. Some views, like text fields are focusable by default. Those that aren’t, can be made focusable using:

  • setFocusable() – in code
  • android:focusable – in XML
  • calling requestFocus() to request that a view take focus
  • using the element in your XML layout file to request focus for a particular view. You can only use this element once per file

You can set views or widgets to be focusable in touch mode using:

  • setFocusableInTouchMode() – in code
  • android:focusableInTouchMode – in XML

Check for focus

If you need to see if a view can receive focus, use:

  • isFocusable() – it returns true or false
  • isFocusableInTouchMode() – checks to see if the view is focusable in touch mode. (A view may be focusable when using a hardware key but not when the device is in touch mode)

Make it happen: Forcing focus

You can force a view to take focus by:

  • calling requestFocus() to request that a view take focus
  • using the element in your XML layout file to request focus for a particular view. You can only use this element once per file

Keep your eye on the ball: Looking for a change in focus?

Implement the OnFocusChangeListener interface to listen for when a view’s focus changes. The interface’s onFocusChange() method is triggered as soon as its attached view’s focus changes.

To and fro: Moving in and out of touch mode

Don’t rely on selection (selected items in a list for example) and focus being maintained as you move in and out of touch mode

All selected items are unselected when the device enters touch mode. They’re reselected when the device exits touch mode.

Similarly any views that are in focus lose their focus when entering touch mode unless they’re focusable in touch mode.

Getting down and dirty: Some sample code

An event is triggered when the user interacts with your app by clicking a button or touching the screen. You can listen for these events using listeners and then use their callback methods to run some code.

If there is no view to handle a touch event, then nothing happens. However, you can include the Activity class’s onTouchEvent() method to handle the event. It will handle any event that is not consumed by any of the other views in the layout.

Stay in touch: The onTouchEvent()

A touch event contains information about the touch. It would, for example contain the following information:

  • the action performed, like ACTION_DOWN or ACTION_UP
  • the X and Y coordinates of where the touch happened on the screen
  • information about the pressure of the touch
  • information about the size and area of the screen contact

This information is contained in a MotionEvent object.

The onTouchEvent() method handles any touch event that has not been consumed by any other view. It receives a MotionEvent object as a parameter.

Here’s an example:

Android Touch Mode and focus onTouchEvent()

The Activity’s onTouchEvent() method is triggered when no other view consumes a touch event

A quick explanation

Let’s say the user touches the screen. This triggers a touch event. If there are no views registered to listen for this event then nothing happens. However if you include the onTouchEvent() method, then it will handle the touch event.

Here we’ve used the onTouchEvent() method to capture the touch event. We then use a switch statement to filter the MotionEvent parameter and display an appropriate LogCat message for the touch action.

The onTouchEvent() method will not trigger if the touch event is consumed by any view in the view hierarchy. For example, if we set an on touch listener on the layout container as shown below:

Android Touch Mode and focus setOnTouchListener()

This listener triggers its onTouch() method when the user touches the screen but it does not consume the event as it returns false

A quick explanation

Although this on touch listener’s onTouch() method handles the touch event, it returns false so does not consume the event. In this case the onTouchEvent() method will still be triggered.

Had the onTouch() method returned true, indicating that it had consumed the event, then the onTouchEvent() method will not be triggered.

In the know! Want to know when a view’s focus changes?

Implement the OnFocusChangeListener interface to monitor when a view’s focus changes:

Android Touch Mode and focus setOnFocusChangeListener()

Implement the OnFocusChangeListener interface to notify you when a view’s focus changes

A quick explanation

The EditTextActivity activity implements the OnFocusChangeListener interface which monitors the view it is attached to for focus change. It’s onFocusChange() method is triggered when either of the text field’s focus changes as we’ve registered the  focus change listener to all of the EditText views.

Here we display a LogCat message indicating which of the text field’s focus has changed, using the text field’s tag attribute value to identify the text field. The tag is defined in the activity’s layout file.

Listen up: Are you listening?

Implementing the listener interfaces

You use event listeners to listen for user interaction. Their callback methods are triggered when the user touches any of the views on the screen.

We’ve implemented a number of listener interfaces to the ButtonsActivity activity in the example below. These are the:

  • OnFocusChangeListener – listens for when a view’s focus changes
  • OnClickListener – listens for when a view is clicked
  • OnGlobalFocusChangeListener – listens for when the focus of any view in a particular view hierarchy changes
  • OnTouchModeChangeListener – listens for when the device’s touch mode changes

Here’s the declaration of the ButtonsActivity activity class:

Android Touch Mode and focus implements listeners

Implement the various listener interfaces in the activity to monitor any changes

A quick explanation

We’ve implemented a number of interfaces to listen for changes in focus, touch mode and button clicks.

We also need to register their callback methods to the various views that we would like to monitor.

Pairing up: Register the listeners

Register the focus change and on click listeners to the various buttons:

Android Touch Mode and focus register Listeners

Register the listeners to the various buttons

A quick explanation

We get references to the 4 buttons and then register the OnFocusChangeListener and OnClickListener to these buttons. This will trigger their callback methods when the buttons are clicked or their focus changes.

Under observation: The observers

We need a ViewTreeObserver for two of the interfaces:

  • OnGlobalFocusChangeListener
  • OnTouchModeChangeListener

Can’t see the wood for the trees: What’s a view tree?

A view tree is a hierarchy of views. For example, a layout file has a single root element which is usually a ViewGroup like a LinearLayout or RelativeLayout. It can contain a number of child views like buttons, text fields and images.

So the ViewGroup can be seen as the trunk of the tree and the child views as the branches. Together they make up the view tree.

Watching the garden grow: What’s a ViewTreeObserver?

We want to listen for changes in a layout (a view tree). To do this, we need to register a listener on the layout or view tree. We use a ViewTreeObserver to do this.

Our layout

Our layout consists of a RelativeLayout containing 4 buttons.

The Buttons

Here’s an example of how we defined one of our buttons in the layout file:

Android Touch Mode and focus Button

There are four buttons. Each has an ID and a tag

A quick explanation

We define the buttons in the XML layout file. Note these attributes:

  • focusable – enables this button to receive focus
  • focusableInTouchMode – enables this button to receive focus when the device is in touch mode
  • tag – a string identity for this button

Get a reference to the ViewGroup container

Android Touch Mode and focus ViewTreeObservers

Get a reference to the ViewGroup and then call getViewTreeObserver() to get the ViewTreeObserver

A quick explanation

We get a reference to the layout’s root element, the RelativeLayout. Then for interest sake, we check if the device is in touch mode by calling isInTouchMode().

Next, we call getViewTreeObserver() to get an instance of a ViewTreeObserver. Then we call isAlive() to check if the observer is alive. (Calling the add…() methods would throw an exception if the observer was not alive).

If the observer is alive then we add the two listeners.

Callback time

World events: The onGlobalFocusChanged() method

The onGlobalFocusChanged() method is triggered whenever focus changes for any of the views in the view hierarchy.

Android Touch Mode and focus globalfocuschanged

The onGlobalFocusChanged() method is triggered when any of the view’s focus changes

A quick explanation

The onGlobalFocusChanged() method is triggered when the focus of any of the views in the view tree changes. We display a LogCat message indicating which view has lost focus and which view has gained focus. (We use the view’s tags, which were defined in the layout file, to identify them.)

Touchy, touchy: The onTouchModeChanged() method

The onTouchModeChanged() method is triggered when the device moves in and out of touch mode. (This happens whenever the user touches the screen or a hardware button).

Android Touch Mode and focus onTouchModeChanged()

The onTouchModeChanged() method is triggered whenever the device enters or leaves touch mode

A quick explanation

The onTouchModeChanged() method is triggered when the user touches the device ‘s screen or when they touch a hardware key.

Here we simply display an appropriate LogCat message when the touch mode changes.

Click, click: The onClick() method

The onClick() method is triggered when one of the buttons is clicked.

Android Touch Mode and focus onClick()

Clicking a button triggers the onClick() method

A quick explanation

Clicking a button triggers its registered OnClickListener interface’s onClick() method. We use a switch statement to filter the clicked button’s ID. If it matches one of the case statements then we display a LogCat message indicating which button was clicked, using the button’s tag to identify it.

We also call the requestFocus() method to place another button in focus.

Touch or not to touch: Is the device in Touch Mode?

You can check at any time to see whether a device is in touch mode.

Android Touch Mode and focus isInTouchMode()

Call the isInTouchMode() method to check whether a device is in touch mode

A quick explanation

A device enters touch mode when the user touches the screen. It remains in touch mode until the user touches a hardware key.

Here we display a LogCat message indicating whether or not the device is in touch mode.

Doing it all over again: The onResume() method

We also check if the device is in touch mode by calling isInTouchMode() in the onResume() method.

Android Touch Mode and focus onResume()

You can check whether a device is in touch mode by calling isInTouchMode() in the activity’s onResume() method as it’s always called just before the activity starts interacting with the user

A quick explanation

It may happen that the activity starts while the device is not in touch mode. The user then navigates to another activity by pressing a virtual button on the screen (putting the device into touch mode). They then return to the previous activity, onResume() is triggered and isInTouchMode() called, showing that the device is now in touch mode.

The LogCat display

Android Touch Mode and focus onResume() logCat

A possible display of the logCat

A quick explanation

When onResume() is triggered for the first time, the device is not in touch mode, later when it’s called again (the user has navigated away from the activity and then returned, triggering onResume()), the device is shown to be in touch mode – indicating that the user had touched the screen at some stage before returning to the activity.

Other kids on the block: More listeners

Here are a couple of examples of other listener interfaces and their callback methods.

The OnTouchListener interface

The on touch listener interface listens for when the view that it is attached to is touched. When the view is touched, it triggers the interface’s onTouch() callback method.

You can implement the listener interfaces in your activities and then register their callbacks on the relevant views as we have done in some of the above examples.

Here we define the OnTouchListener interface as an anonymous class which is passed to the setOnTouchListener() method to register the interface on the ImageView:

Android Touch Mode and focus setOnTouchListener()

Implement the OnTouchListener as an inner class which is passed to the setOnTouchListener() method

A quick explanation

The listener triggers its onTouch() method when the ImageView is touched.

We use a switch statement to filter the MotionEvent parameter and then display the appropriate LogCat message.

We also use an intent to start the ButtonsActivity activity.

All the return values are true, indicating that this listener has consumed the touch event.

The OnLongClickListener interface

Use the OnLongClickListener interface to listen for when the user clicks and holds a view.

Android Touch Mode and focus setOnLongClickListener()

The OnLongClickListener interface’s onLongClick() method triggers when a user clicks and holds the view

A quick explanation

We implement the OnLongClickListener interface as an inner class, passing it as a parameter to the setOnLongClickListener() method to register the interface of the ImageView.

Each time the ImageView is long-clicked, the onLongClick() method triggers, displaying a message in the LogCat.

The OnClickListener interface

The OnClickListener interface listens for when a view is clicked.

Android Touch Mode and focus setOnClickListener()

Clicking a view triggers the OnClickListener interface’s onClick() callback method

A quick explanation

The interface’s onClick() method is triggered each time the imageButton is clicked. Here we display a LogCat message and start the EditTextActivity activity.

I hope that you found this tutorial helpful.

Here are a couple of tutorials that you may also find useful:

Android: Using touch gestures

Using Android’s Log class API to debug Android application code

Android Buttons tutorial

Related items