Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Apparently the "disappearing selection" is by design; it's something called "<a href="http://developer.android.com/resources/articles/touch-mode.html">touch mode</a>". I read through that document and still I have no idea why they thought it was a good idea. My guess is that, since Android was originally designed for small-screen devices, they expected that you would fill the screen with a list and then, when the user clicks an item, move to a new list on a different screen. Thus, the user wouldn't be aware that Android lost track of the selected item.</p> <p>But this behavior is quite annoying if, for example, you want the user to select an item and then show information about that item on the same screen. If the selection disappears, how is the user supposed to know what they clicked (assuming of course that users have the attention span of a goldfish)?</p> <p>One possible solution is to change all the list items into radio buttons. I don't really like that solution because it wastes screen real estate. I'd rather just use the background color to show which item is selected. I have seen one solution so far but it is not quite complete or general. So here's my solution:</p> <h2>1. In your XML layout file</h2> <p>Go to your ListView element and the following attribute: <code>android:choiceMode="singleChoice"</code>. I'm not entirely sure what this does (by itself, it doesn't allow the user to select anything) but without this attribute, the code below doesn't work.</p> <h2>2. Define the following class</h2> <p>It is used to keep track of the selected item, and also allows you to simulate pass-by-reference in Java:</p> <pre><code>public class IntHolder { public int value; public IntHolder() {} public IntHolder(int v) { value = v; } } </code></pre> <h2>3. Put the following code somewhere</h2> <p>I'll assume you put it in your Activity, but it could go in any class really:</p> <pre><code>static void setListItems(Context context, AdapterView listView, List listItems, final IntHolder selectedPosition) { setListItems(context, listView, listItems, selectedPosition, android.R.layout.simple_list_item_1, android.R.layout.simple_spinner_dropdown_item); } static void setListItems(Context context, AdapterView listView, List listItems, final IntHolder selectedPosition, int list_item_id, int dropdown_id) { listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { public void onItemClick(AdapterView&lt;?&gt; list, View lv, int position, long id) { selectedPosition.value = position; } }); ArrayAdapter&lt;CharSequence&gt; adapter = new ArrayAdapter&lt;CharSequence&gt;(context, list_item_id, listItems) { @Override public View getView(int position, View convertView, ViewGroup parent) { View itemView = super.getView(position, convertView, parent); if (selectedPosition.value == position) itemView.setBackgroundColor(0xA0FF8000); // orange else itemView.setBackgroundColor(Color.TRANSPARENT); return itemView; } }; adapter.setDropDownViewResource(dropdown_id); listView.setAdapter(adapter); } </code></pre> <p>This code does two things: it attaches your list items (e.g. <code>List&lt;String&gt;</code>) to your ListView, and it overrides <code>ArrayAdapter.getView()</code> with some code that changes the background of the selected item.</p> <h2>4. Use that code to set up your list</h2> <p>For example:</p> <pre><code>ListView _list; IntHolder _selectedItem = new IntHolder(-1); // nothing selected at first @Override protected void onCreate(Bundle savedInstanceState) { ... _list = (ListView)findViewById(R.id.list); List&lt;String&gt; items = Arrays.asList("Item 1", "Item 2", "Item 3"); setListItems(this, _list, items, _selectedItem); } </code></pre> <p>That's all! The above assumes you want single selection. With some small modifications to getView(), you could support multi-selection too, I guess, but you should probably use checkboxes instead.</p> <p><strong>Warning</strong>: this solution needs further development. If the user uses arrow keys or buttons to select an item, that item will <strong>not</strong> be selected from the IntHolder's perspective. If the user presses the unlabeled button (what's the name of that button? "Enter"?) then the item will become "officially" selected but then you have another problem because if the user uses the arrow keys again, it will sort of look like two items are selected. Leave a comment if you figure out how to keep the "internal selection" in the IntHolder synchronized with the "keyboard selection" or whatever it's called. What <em>is</em> it called, anyway?</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