Android - Keep ListView's item highlighted once one has been clicked
So I have an activity with 2 ListView
widgets, when you select a value in the first one, the second is populated with values related to the selection in the first ListView
. This mechanic works without a problem, but now I want the user choices to stay highlighted. I've read a good ammount of question related to this topic and it seems there is a myriad of ways one can accomplish this but after trying about 4-5 of em' I still can't get it to work.
I've got it working on the second ListView
using the android:listSelector="#CCCCCC"
XML Attribute, but this seems to be wiped clean once a OnItemClickListener
is introduced into the mix (like the one I use on my first ListView
).
So far here's what I've got:
Custom OnItemClickListener
I found browsing various answer regarding this topic (slightly modified it in order for it to load my info the second ListView):
private class ItemHighlighterListener implements OnItemClickListener {
private View oldSelection = null;
public void clearSelection() {
if(oldSelection != null) {
oldSelection.setBackgroundColor(android.R.color.transparent);
}
}
public void onItemClick(AdapterView<?> parent, View view, int pos, long id) {
clearSelection();
oldSelection = view;
view.setBackgroundDrawable(view.getContext().getResources().getDrawable(R.drawable.list_selector));
loadClubs(mXMLPortalOptions.getRegion(pos).getId());
mClubList.setAdapter(new ArrayAdapter<String>(getApplicationContext(), R.layout.list_item_white, mClubs));
}
}
Here's my list_selector.xml
file :
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true"><shape>
<solid android:color="#CCCCCC" />
</shape></item>
<item android:state_selected="false"><shape>
<solid android:color="#FFFFFF" />
</shape></item>
</selector>
The method (OnItemClick) is called and executed, but the background of my ListItem
stays the same color :/
I can't believe that this simple task has proven so complicated.
If I have omitted code that could be useful or if my question is lacking details, feel free to point that out and I'll do my best to explain myself.
Solution 1:
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);
}
}
Solution 2:
To expand on Shaiful's great solution, you might not get his to work in your situation.
If you are using have your code all in public void onListItemClick(ListView l, View v, int index, long id)
, if you're using fragments and have to declare an interface instead of implementing OnListItemClickListener, or whatever is causing your IDE to generate errors, you might have to access variables and methods statically.
public static int selectedPosition = 0;
ArrayAdapter<Your_obj> adapter = null;
@Override
public void onListItemClick(ListView l, View v, int index, long id) {
super.onListItemClick(l, v, index, id);
selectedPosition = index;
Your_adapter.setSelectedIndex(selectedPosition);
adapter.notifyDataSetChanged();
}
And in Your_adapter:
private static int selectedIndex;
//public Your_adapter...
public static void setSelectedIndex(int ind) {
selectedIndex = ind;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
WellHolder holder = null;
if (null == convertView) {
//set up your "holder"
}
if (position == selectedIndex) {
convertView.setBackgroundColor(convertView.getResources().getColor(R.color.cyan));
}
else {
convertView.setBackgroundColor(convertView.getResources().getColor(R.color.silver));
}
return convertView;
}
Some other differences are that you don't have to initialize any variables as "0" or "-1" and notifyDataSetChanged() is called in your activity.
Once again, thanks for your solution @Shaiful. It certainly helped save me time trying to get what is default in iOS to work for Android, all while avoiding selector/item/focused/pressed/etc.
Solution 3:
I faced similar problem. That's my solution:
First add custom list selector to your list view:
<ListView
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:listSelector="@drawable/listselector" />
Inside listselector.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_accelerated="false"
android:drawable="@drawable/bg" />
</selector>
And finally a drawable bg.xml with color of your highlight:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#33b5e6"/>
</shape>