ListView state_selected lost on real device

I have a problem with a simple ListView on a Samsung phone.

I am creating a new ListView programmatically. Elements are simple TextView. I put the listener on my list:

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

TextView (i.e. listView elements) use a ColorStateList as textColor (pressed β†’ green, selected β†’ blue, default β†’ red).

Everything is fine on the emulator: by default, red objects when I press one, it turns green, and when I release it, it turns blue. If I select another item: the previously selected one will return to red, and the newly selected will turn blue.

On my Samsung device: by default, red elements turn red when I press one, it turns green, and when I release it, it turns red again (i.e. not selected).

This seems to be a bug in the implementation of Samsung ListView (it is a custom implementation and it is so difficult to track without source code).

EDIT : not an error, but slightly different behavior due to touch mode (see link in accepted answer)

Do you have any ideas on how to handle this error / behavior?

Additional limitation: I cannot use the xml selector because I get the color for use only at runtime.

My device is Samsung GT-B5330, API 15. (but I expect this to happen on most Samsung devices).

Here is the complete (compiled) code

 import android.R; import android.app.Activity; import android.content.res.ColorStateList; import android.database.DataSetObserver; import android.graphics.Color; import android.os.Bundle; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.ListAdapter; import android.widget.ListView; import android.widget.RelativeLayout; import android.widget.TextView; public class TestActivity extends Activity { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); RelativeLayout rootLayout = new RelativeLayout(this); setContentView(rootLayout); //create listView ListView listView = new ListView(this); listView.setAdapter(new MyListAdapter()); listView.setDivider(null); listView.setDividerHeight(0); listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE); listView.setItemsCanFocus(false); listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { view.setSelected(true); } }); listView.setBackgroundColor(Color.WHITE); //positionning listView RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(100,200); lp.setMargins(50,50,10,10); rootLayout.addView(listView, lp); } private class MyListAdapter implements ListAdapter{ @Override public View getView(int position, View convertView, ViewGroup parent) { ColorStateList colorStateList = new ColorStateList( new int[][]{ new int[]{R.attr.state_pressed}, new int[]{R.attr.state_selected}, new int[]{-R.attr.state_selected}, }, new int[]{ Color.GREEN, Color.BLUE, Color.RED}); TextView textView = new TextView(parent.getContext()); textView.setText("Item " + position); textView.setTextColor(colorStateList); return textView; } @Override public boolean areAllItemsEnabled() { return true; } @Override public boolean isEnabled(int position) { return true; } @Override public void registerDataSetObserver(DataSetObserver observer) { } @Override public void unregisterDataSetObserver(DataSetObserver observer) { } @Override public int getCount() { return 10; } @Override public Object getItem(int position) { return "data "+position; } @Override public long getItemId(int position) { return position; } @Override public boolean hasStableIds() { return true; } @Override public int getItemViewType(int position) { return position; } @Override public int getViewTypeCount() { return getCount(); } @Override public boolean isEmpty() { return getCount()>0; } } } 
+3
java android samsung-mobile android-listview
source share
2 answers

I don’t have a samsung device at hand (Galaxy Nexus dosen't count, it has a simple Android and it works fine with your example), so I can’t check my assumptions, but it seems that ListView leaves the selected state after it was released. You can check it with the HierarchyViewer (use Romain Guy ViewServer if your phone is not rooted).

It is dangerous to rely on a choice having a touch screen due to TouchMode (see http://android-developers.blogspot.ru/2008/12/touch-mode.html ). In a nutshell: you don’t have the concept of choice (or focus, by the way) when the user interacts with the touch screen. An emulator usually has a D-pad, so it may have slightly different behavior.

So my suggestion for you is to use state_checked instead of state_selected . Android CheckedTextView can help. Just call ListView setItemChecked . This solution also has good properties of preserving the position of a position between configuration changes and automatically CHOICE_MODE_SINGLE previously marked item when another item is pressed (if CHOICE_MODE_SINGLE used).

If this is unacceptable and you need to adhere to state_selected , then you can wrap the TextView in a LinearLayout to prevent the selection from fading. But do not forget that ListView reuses the same view for other list items when it exits the screen, so you need to monitor the selection state in your adapter in order to set it correctly.

+1
source share

I can confirm, I experienced a similar error only on Samsung devices (Nexus, S3, Note2). The Listview element has a default background color, so in my case it is black. But randomly, it turns red. If I set the listviewitem to explicitly black for the background, I did not experience the error. Honestly, I don’t know what to do in your case, but determining the colors of the entire state can help you.

0
source share

All Articles