Android Listview Selected Item Stay Highlighted

Android ListView selected item stay highlighted

To hold the color of listview item when you press it, include the following line in your listview item layout:

android:background="@drawable/bg_key"

Then define bg_key.xml in drawable folder like this:

<?xml version="1.0" encoding="utf-8" ?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:state_selected="true"
android:drawable="@color/pressed_color"/>
<item
android:drawable="@color/default_color" />
</selector>

Finally, include this in your ListView onClickListener:

listView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position,long arg3) {
view.setSelected(true);
... // Anything
}
});

This way, only one item will be color-selected at any time. You can define your color values in res/values/colors.xml with something like this:

<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="pressed_color">#4d90fe</color>
<color name="default_color">#ffffff</color>
</resources>

Android - Keep ListView's item highlighted once one has been clicked

Put a position variable for selected item. Change the position in onItemClicked() method. Check the selected position in List Adapter inside getView() and set the background for the selected item.

public class TestAdapter extends BaseAdapter
{
private Context context;
private ArrayList<TestList> testList;
private int selectedIndex;
private int selectedColor = Color.parseColor("#1b1b1b");

public TestAdapter(Context ctx, ArrayList<TestList> testList)
{
this.context = ctx;
this.testList = testList;
selectedIndex = -1;
}

public void setSelectedIndex(int ind)
{
selectedIndex = ind;
notifyDataSetChanged();
}

@Override
public int getCount()
{
return testList.size();
}

@Override
public Object getItem(int position)
{
return testList.get(position);
}

@Override
public long getItemId(int position)
{
return position;
}

private class ViewHolder
{
TextView tv;
}

@Override
public View getView(int position, View convertView, ViewGroup parent)
{
View vi = convertView;
ViewHolder holder;
if(convertView == null)
{
vi = LayoutInflater.from(context).inflate(R.layout.test_list_item, null);
holder = new ViewHolder();

holder.tv = (TextView) vi;

vi.setTag(holder);
}
else
{
holder = (ViewHolder) vi.getTag();
}

if(selectedIndex!= -1 && position == selectedIndex)
{
holder.tv.setBackgroundColor(Color.BLACK);
}
else
{
holder.tv.setBackgroundColor(selectedColor);
}
holder.tv.setText("" + (position + 1) + " " + testList.get(position).getTestText());

return vi;
}

}

Now set the selectedIndex variable when a list item clicked.

public class TestActivity extends Activity implements OnItemClickListener
{
// Implemented onItemClickListener

@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
{
adapter.setSelectedIndex(position);
}
}

ListView stay selected?

Apparently the "disappearing selection" is by design; it's something called "touch mode". 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.

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)?

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:

1. In your XML layout file

Go to your ListView element and the following attribute: android:choiceMode="singleChoice". 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.

2. Define the following class

It is used to keep track of the selected item, and also allows you to simulate pass-by-reference in Java:

public class IntHolder {
public int value;
public IntHolder() {}
public IntHolder(int v) { value = v; }
}

3. Put the following code somewhere

I'll assume you put it in your Activity, but it could go in any class really:

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<?> list, View lv, int position, long id) {
selectedPosition.value = position;
}
});
ArrayAdapter<CharSequence> adapter = new ArrayAdapter<CharSequence>(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);
}

This code does two things: it attaches your list items (e.g. List<String>) to your ListView, and it overrides ArrayAdapter.getView() with some code that changes the background of the selected item.

4. Use that code to set up your list

For example:

ListView _list;
IntHolder _selectedItem = new IntHolder(-1); // nothing selected at first

@Override
protected void onCreate(Bundle savedInstanceState) {
...
_list = (ListView)findViewById(R.id.list);
List<String> items = Arrays.asList("Item 1", "Item 2", "Item 3");
setListItems(this, _list, items, _selectedItem);
}

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.

Warning: this solution needs further development. If the user uses arrow keys or buttons to select an item, that item will not 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 is it called, anyway?

Why is my ListView item selected, but not highlighted after click?

Although @jyomin provided a solution to my problem it may generate a few bugs:

  • When user scrolls (down or up) enough to hide the selected item, it will return to the unselected state.
  • If user touches the screen (at any place) it will remove the ListView item focus.

That being said (and tested), I decided to find another workaround to my old code, as I want to not only highlight but activate the ListView item.

I found out that I was setting the background behavior at the wrong place. It should have been set before at the LinearLayout inside list_item_layout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:background="@layout/list_selected" >

<ImageView
android:id="@+id/imageView1"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_gravity="center"
android:layout_marginLeft="20dp"
android:scaleType="fitCenter"
android:src="@drawable/datahora" />

<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginLeft="20dp"
android:layout_marginRight="10dp"
android:fontFamily="sans-serif-light"
android:text="TextView"
android:textColor="@layout/text_selected"
android:textSize="22dp" />

</LinearLayout>

Simply added the activated state to the View:

@Override
public void onListItemClick(ListView listView, View view, int position,
long id) {
super.onListItemClick(listView, view, position, id);

view.setSelected(true);
view.setActivated(true);

// Notify the active callbacks interface (the activity, if the
// fragment is attached to one) that an item has been selected.
mCallbacks.onItemSelected(DummyContent.ITEMS.get(position).id);

}

And defined a new selector:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Selected Item -->

<item android:state_selected="true"
android:drawable="@android:color/holo_blue_light" />
<item android:state_activated="true"
android:drawable="@android:color/holo_blue_light" />

<!-- Default Item -->
<item android:state_selected="false"
android:drawable="@android:color/white" />
</selector>

Way to go, Machado. :)

Android: ListView selected item (onClick) stay selected after action

Please remove this from your fragment_xml's listview: android:listSelector="@color/colorListSelected"

or use

android:listSelector="?attr/selectableItemBackground" instead

and if it does not work, you may like to use your own custom style.



Related Topics



Leave a reply



Submit