state_selected ListView项丢失在真实设备 [英] ListView item state_selected is lost on real device
问题描述
我有一个三星手机上的一个简单的ListView的一个问题。
我编程方式创建一个新的ListView。该项目是简单的TextView。我把听众对我的列表视图:
listView.setOnItemClickListener(新AdapterView.OnItemClickListener(){
@覆盖
公共无效onItemClick(适配器视图<>母公司,观景,INT位置,长的id){
view.setSelected(真);
}
});
的的TextView
(即ListView控件的项目)使用 ColorStateList
的文字颜色(pressed - >绿色;选择 - >蓝;默认 - >红)
在模拟器,一切都很好:项红在默认情况下,当我preSS之一,它变成绿色,当我松开变成蓝色。如果我选择另一个项目:pviously选择了$ P $回到红色和新选择成为蓝色
。在我的三星设备:项目默认情况下红色,当我preSS之一,它变成绿色,当我松开再次变成红色(即未选择)
。<击>这似乎是在三星的ListView实现中的错误行使>(这是一个自定义的实现难度大等无源$ C $ C跟踪)。
修改:不是一个错误,但由于触控模式(见接受的答案链接)稍有不同的行为
你有没有对如何解决这个<击>错误/ 击>行为的任何想法?
附加约束:因为我收到的颜色只在运行时使用我不能使用的 XML选择的
我的设备是三星GT-B5330,API 15(但我希望它发生在大多数的三星设备)
下面是完整的(编译)code
进口android.R;
进口android.app.Activity;
进口android.content.res.ColorStateList;
进口android.database.DataSetObserver;
进口android.graphics.Color;
进口android.os.Bundle;
进口android.view.View;
进口android.view.ViewGroup;
进口android.widget.AdapterView;
进口android.widget.ListAdapter;
进口android.widget.ListView;
进口android.widget.RelativeLayout;
进口android.widget.TextView;公共类测试活动扩展了活动{公共无效的onCreate(捆绑savedInstanceState){
super.onCreate(savedInstanceState);
RelativeLayout的rootLayout =新的RelativeLayout(本);
的setContentView(rootLayout); //创建的ListView
ListView控件的ListView =新的ListView(这一点);
listView.setAdapter(新MyListAdapter());
listView.setDivider(NULL);
listView.setDividerHeight(0);
listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
listView.setItemsCanFocus(假);
listView.setOnItemClickListener(新AdapterView.OnItemClickListener(){
@覆盖
公共无效onItemClick(适配器视图&LT;&GT;母公司,观景,INT位置,长的id){
view.setSelected(真);
}
});
listView.setBackgroundColor(Color.WHITE); //为定位的ListView
RelativeLayout.LayoutParams LP =新RelativeLayout.LayoutParams(100,200);
lp.setMargins(50,50,10,10);
rootLayout.addView(ListView中,LP);
}私有类MyListAdapter实现ListAdapter { @覆盖
公共查看getView(INT位置,查看convertView,父母的ViewGroup){
ColorStateList colorStateList =新ColorStateList(
新的INT [] [] {
新的INT [] {R.attr.state_ pressed},
新的INT [] {} R.attr.state_selected,
新的INT [] { - R.attr.state_selected},
},
新的INT [] {
Color.GREEN,
Color.BLUE,
Color.RED});
TextView中的TextView =新的TextView(parent.getContext());
textView.setText(项目+位置);
textView.setTextColor(colorStateList);
返回的TextView;
} @覆盖
公共布尔areAllItemsEnabled(){
返回true;
} @覆盖
公共布尔isEnabled(INT位置){
返回true;
} @覆盖
公共无效registerDataSetObserver(DataSetObserver观察者){
} @覆盖
公共无效unregisterDataSetObserver(DataSetObserver观察者){
} @覆盖
公众诠释的getCount(){
返回10;
} @覆盖
公共对象的getItem(INT位置){
回归数据+位置;
} @覆盖
众长getItemId(INT位置){
返回的位置;
} @覆盖
公共布尔hasStableIds(){
返回true;
}
@覆盖
公众诠释getItemViewType(INT位置){
返回的位置;
} @覆盖
公众诠释getViewTypeCount(){
返回的getCount();
} @覆盖
公共布尔的isEmpty(){
返回的getCount()大于0;
}
}
}
我没有手头上有三星设备(Galaxy Nexus的这么想的计算,它具有普通Android和它的工作原理相当精细与你的例子),所以我不能测试我的假设,但似乎选择的ListView滴的项目状态已经释放之后。你可以用HierarchyViewer检查(使用罗曼盖伊的 ViewServer 如果你的手机是不是植根)。
这是很危险的依靠有选择,因为TouchMode的的触摸屏(见的 http://android-developers.blogspot.ru/2008/12/touch-mode.html )。在两句话:你没有选择的概念(或焦点,顺便说一句),当用户使用触摸屏进行交互。仿真器通常有D垫,因此它可能略有不同的行为。
所以,我对你的建议是使用 state_checked
而不是 state_selected
的。 Android有 CheckedTextView 这可能会有帮助。只需调用ListView的 setItemChecked
。该解决方案还具有保持配置更改和全自动取消选中$ P $的检查项目位置pviously检查项目,当其他项目pressed的良好特性(如 CHOICE_MODE_SINGLE
时)
如果这是不能接受的,您需要使用 state_selected
坚持,那么你可以换你的TextView到LinearLayout中,应该从$消失p $ pvent选择。但是不要忘记,ListView控件重用其他列表项相同的观点,当它熄灭屏幕,所以你需要追踪您的适配器选择状态正确设置它。
I have a problem with a simple ListView on a Samsung phone.
I create a new ListView programmatically. The items are simple TextView. I put a listener on my list view:
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
view.setSelected(true);
}
});
The TextView
(i.e. items of listView) use a ColorStateList
as textColor (pressed-->Green ; selected-->Blue ; default-->Red).
On the emulator, everything is fine : items are red by default , when I press one it become green, and when I release it become blue. If I select another item : the previously selected go back to red and the newly selected became blue.
On my Samsung device : items are red by default , when I press one it become green, and when I release it become red again (i.e. not selected).
It seems to be a bug in the Samsung ListView implementation (it's a custom implementation and so difficult to trace without source code).
EDIT: not a bug but a slightly different behavior because of touch mode (see link in accepted answer)
Do you have any ideas on how to workaround this bug/behavior?
Additional constraint: I can't use an xml selector because I receive the color to use only at runtime.
My device is a Samsung GT-B5330 , API 15. (but I expect it occurs on most Samsung devices)
Here is the complete (compilable) 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;
}
}
}
I don't have a samsung device on hand (Galaxy Nexus dosen't count, it has plain Android and it works quite fine with your example) so I cannot test my assumptions but it seems that ListView drops selected state of the item after it has been released. You can check it with HierarchyViewer (use Romain Guy's ViewServer if your phone isn't rooted).
It is dangerous to rely on selection having a touchscreen because of TouchMode (see http://android-developers.blogspot.ru/2008/12/touch-mode.html). In two words: you don't have a concept of selection (or focus, btw) when a user is interacting with a touchscreen. Emulator usually has D-pad so it may have slightly different behavior.
So my suggestion for you is to use state_checked
instead of state_selected
. Android has CheckedTextView that may help. Just call ListView's setItemChecked
. This solution also has nice properties of keeping checked item position between configuration changes and automatical unchecking previously checked item when other item is pressed (if CHOICE_MODE_SINGLE
is used).
If it is not acceptable and you need to stick with state_selected
then you may wrap your TextView into LinearLayout, it should prevent selection from disappearing. But don't forget that ListView reuses the same view for other list items when it goes out of screen, so you need to track selection state in your adapter to properly set it.
这篇关于state_selected ListView项丢失在真实设备的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!