Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Sorry, answered my own question. It may not be the most correct or most elegant solution, but it works for me, and gives a pretty solid user experience. I looked into the code for ListView to see why the two behaviors are so different, and came across this from ListView.java:</p> <pre><code> public void setItemsCanFocus(boolean itemsCanFocus) { mItemsCanFocus = itemsCanFocus; if (!itemsCanFocus) { setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS); } } </code></pre> <p>So, when calling <code>setItemsCanFocus(false)</code>, it's also setting descendant focusability such that no child can get focus. This explains why I couldn't just toggle <code>mItemsCanFocus</code> in the ListView's OnItemSelectedListener -- because the ListView was then blocking focus to all children.</p> <p>What I have now:</p> <pre><code>&lt;ListView android:id="@android:id/list" android:layout_height="match_parent" android:layout_width="match_parent" android:descendantFocusability="beforeDescendants" /&gt; </code></pre> <p>I use <code>beforeDescendants</code> because the selector will only be drawn when the ListView itself (not a child) has focus, so the default behavior needs to be that the ListView takes focus first and draws selectors.</p> <p>Then in the OnItemSelectedListener, since I know which header view I want to override the selector (would take more work to dynamically determine if any given position contains a focusable view), I can change descendant focusability, and set focus on the EditText. And when I navigate out of that header, change it back it again.</p> <pre><code>public void onItemSelected(AdapterView&lt;?&gt; listView, View view, int position, long id) { if (position == 1) { // listView.setItemsCanFocus(true); // Use afterDescendants, because I don't want the ListView to steal focus listView.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS); myEditText.requestFocus(); } else { if (!listView.isFocused()) { // listView.setItemsCanFocus(false); // Use beforeDescendants so that the EditText doesn't re-take focus listView.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS); listView.requestFocus(); } } } public void onNothingSelected(AdapterView&lt;?&gt; listView) { // This happens when you start scrolling, so we need to prevent it from staying // in the afterDescendants mode if the EditText was focused listView.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS); } </code></pre> <p>Note the commented-out <code>setItemsCanFocus</code> calls. With those calls, I got the correct behavior, but <code>setItemsCanFocus(false)</code> caused focus to jump from the EditText, to another widget outside of the ListView, back to the ListView and displayed the selector on the next selected item, and that jumping focus was distracting. Removing the ItemsCanFocus change, and just toggling descendant focusability got me the desired behavior. All items draw the selector as normal, but when getting to the row with the EditText, it focused on the text field instead. Then when continuing out of that EditText, it started drawing the selector again.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload