After reading the answer from @Raj, going through the Android documentation, and experimenting with the code, I think I understand how they work a little better now. Here is a little additional help if anyone else is similarly confused. Let me know if I've got it wrong.
Views can be focused or unfocused. Some views change their appearance when they are focused. This can be especially useful when using a keypad to navigate the layout. This way you know where you are before you actually click a view. Even views that do not naturally change when focus can be made to do so by using a selector and drawables. If you are not using a keypad to navigate, though, focus is not as important.
There were three pairs of things that were confusing me:
isFocusable()
isFocusableInTouchMode()
setFocusable()
setFocusableInTouchMode()
requestFocus()
requestFocusFromTouch()
The first pair just tells you information about the view. That is, whether or not it is even possible for that view to be focused. You can find out by doing something like this:
Boolean b = myView.isFocusable();
You are in touch mode after you have touched the screen. So something that may be focusable when you are using the keypad may not be focusable when you are using your fingers. You can check like this:
Boolean b = myView.isFocusableInTouchMode();
Like I said, this only tells you information about whether it is even possible to give the view focus or not. If you want to actually give the view focus, first you have to make it possible to be focused. You can do this with one of the following commands:
myView.setFocusable(true);
myView.setFocusableInTouchMode(true);
If you are in touch mode and you call setFocusableInTouchMode(true)
then both myView.isFocusable()
and myView.isFocusableInTouchMode()
will return true. You don't need to call them both. However, if you only call myView.setFocusable(true)
then myView.isFocusableInTouchMode()
will not be changed.
Now to finally make the view focused you have to call the following:
myView.requestFocus();
I still don't fully understand requestFocusInTouchMode()
because just using requestFocus()
worked for me, but the documentation says about requestFocusInTouchMode()
:
Call this to try to give focus to a specific view or to one of its descendants. This is a special variant of requestFocus() that will allow views that are not focuable in touch mode to request focus when they are touched.
Finally, it should be noted that Romain Guy said in this post:
A view that's focusable in touch mode has weird interactions and unless you perfectly understand what you are doing you should NOT use it. requestFocus() works, but focus is shown only when the device is not in touch mode. As soon as the user touches the screen, the focus is not displayed anymore. By doing what you are doing you are making your app behave differently from the rest of the system and you risk weird behaviors.