javaandroidfocusable

How do clearFocus() and focusableInTouchMode="true" work together?


I would like someone to explain the 2 following behaviors.

I start with this screen:

enter image description here

When I touch the text area inside "City You're From", I get the following screen: enter image description here

When I hit the keyboard's "Done" button, I go back to the original state as expected. In other words, the hidden boxes are made visible again and the cursor is gone( the EditText no longer has focus ). How this happens is I just have a listener waiting for that "Done" button to be pressed. When that happens, I call clearFocus() on the EditText view. I then have a OnFocusChangeListener which makes all the boxes invisible/visible depending on whether an EditText has focus or not.

HOWEVER, I only get this expected behavior when I set an ancestor layout (i.e. a parent or grandparent RelativeLayout) with the following property: android:focusableInTouchMode="true"

OTHERWISE, I get the following screen:

enter image description here

When clearFocus() is called, it jumps down to the next child in the hieararchy which is "Current City" and gives that EditText focus (and hides the keyboard but that's part of the expected behavior).

Clicking on "Current City" in screen 1 results in screen 3 as well if I do not set android:focusableInTouchMode="true". In other words, it remains at "Current City" and does not lose focus.

Question Can someone please explain what is going on? Why does leaving out android:focusableInTouchMode="true" cause such strange behavior?


Solution

  • I found the answer in the comments above the source code for clearFocus():

    "Called when this view wants to give up focus. If focus is cleared onFocusChanged(boolean,int,android.graphics.Rect) is called. Note: When a View clears focus the framework is trying to give focus to the first focusable View from the top. Hence, if this View is the first from the top that can take focus, then all callbacks related to clearing focus will be invoked after wich the framework will give focus to this view."

    In other words, when a view gives up focus, the framework traverses down the hiearachy starting from the root looking for the first view it can give focus to. When I leave out android:focusableInTouchMode="true", the framework gives the focus to "Current City" because that is the first view it finds that is focusable. When multiple things are focusable on the same level of the hiearchy, the framework starts with the view that is nearest the bottom of the actual xml code. The reason for that is because if 2 views are on the same level in the hierarchy, and you were to place the views at the same position on the screen, the one nearest the bottom of the code will appear on top in the screen.