Friday, August 19, 2011

Focus problems with list rows and ImageButtons

There has been lot of discussions on this blog about some widgets that steal focus from others - creating behaviour that sounds completely illogical for the uninitiated. So far we have seen how Buttons steal the focus from list rows. The same monster rears its ugly head in this slightly different example. Here we have a simple ListView with list rows. Each list row has a text widget and an ImageButton in it. Now if we code this example innocently without being aware of the tricky focus-stealing effect of ImageButton, list rows cannot be selected.

Click here to download the example program.



The example program as it is works nicely. If you click the row, you will get one sort of Toast message. If you click the ImageButton within the row, you will get another Toast message. Now let's observe this XML attribute in res/layout/item.xml:

android:descendantFocusability="blocksDescendants"

Try removing this attribute and notice, that selecting list items does not work anymore. What happened? As explained previously, ImageButton steals the focus from the view group (the list row) it is in. This means that when you click the list row, it is always the ImageButton that captures the event but as it is outside of its screen area, the event is discarded. Therefore we prevented the ImageButton to capture the focus.

Previously I recommended preventing the capture of the focus by making the button non-focusable (android:focusable="false"). Curiously, it does not work in this example so I had to find another way. That's why I shared this example.