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.

21 comments:

Darth Beleg said...

There is a feature of the ImageButton in Android: it cannot be set to non-focusable using xml attribute, because someone explicitly calls setFocusable(true) in the constructor: see the sources. There is an issue submitted, but it seems that the Android team will not fix it: https://review.source.android.com/15203

Gabor Paller said...

Thanks for the explanation, Darth.

I hesitated a bit whether to publish this post - it seemed to be a variation of an old post. But now it is evident that this ImageButton issue needed to be mentioned. :-)

India web hosting said...

Well that’s very Nice work! I would like to appreciate the great work done by the web master and would like to tell everyone that they should post their interesting comments and should make this blog interesting. Once again I would like to say keep it up to blog owner!!! i enjoyed to read this post.

Anonymous said...

Thanks a ton for this post! I had the same issue with a checkbox. If I used focusable=false it caused problems with onCheckedChangedListener. This cleared it up.

Anonymous said...

This is a good article, thanks.

But I would be inclined to put this logic into the code, instead of the layout as this is more of functionality issue then a layout issue.

So I did:

view.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);

on the inflated view.

Vivek said...

Thanx a lot for this Great Post...!! yo yo...my code works robustly...

pramod said...

Thanks buddy my code is working fine now..

GabLeRoux said...

Duuuude, you're a life saver, thanks so much for this, we've been trying to make this work for hours and the solution was a simple line.

Harteg said...

Thanks man !

Anonymous said...

now i dont need to take an advil
thank u

Ramiro Madriaga said...

thanks dude, it was very helfull

Unknown said...

Thanks.. very helpful

Omer said...

Boss you are genius !!

Unknown said...

Thank you

Jolson said...

Thanx bro...got wat i was looking for...

Anonymous said...

many thanks!

Ganesh Kumar said...

Good fix!

gayan said...

Thanks buddy...

Christian said...

Great effort sorted my listview problem!

Anonymous said...

Amazing thanks for help it worked

Anonymous said...

Thank you! Very helpful post!