Lists and focuses

I received another seemingly trivial question in a comment. The situation is simple: we have a ListView and it contains TextViews. The user clicks (touches) a list row and the row gets highlighted until the user removes his or her finger (releases the mouse button in case of the emulator). Then comes the mistery. If you put a Button into the row, this highlight does not happen. How come?

Download the example program from here.

The secret is the quite complicated relationship between the ListView's selection algorithm and the focus. Button is focusable, basic TextView is not (Button is really just a specialized TextView). ViewGroup (whose child is LinearLayout which encapsulates one list row) delegates the focus to its first focusable child if it is not prevented to do so. As list row gives away the focus to the first focusable child (the Button) and the user did not touch the Button's area, neither the list row, nor the Button is selected. All this happens in "touch mode", try to select the row with the down/up key and you will see a completely different selection algorithm in action - the row is highlighted but the Button is not.

In order to achieve the selection effect you see in the screenshot, the ViewGroup must be prevented giving away the focus. The example program implements a quick and dirty solution: the Button is not focusable (ButtonListAdapter, line 47). More elegant solution would be to declare the ViewGroup (inflated from the buttonrow.xml layout) with FOCUS_BLOCK_DESCENDANTS flag. Conveniently, not being focusable does not prevent the Button in receiving events, click on the action button and the row counter increases nicely.

Comentarios 1 link Destacados

Comentarios 1 link Destacados