ListView项state_selected在实际设备上丢失

时间:2013-01-09 14:56:05

标签: java android android-listview samsung-mobile

我在三星手机上遇到一个简单的ListView问题。

我以编程方式创建一个新的ListView。这些项目是简单的TextView。我在我的列表视图中放了一个监听器:

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

TextView(即listView的项目)使用ColorStateList作为textColor(按下 - &gt;绿色;选中 - &gt;蓝色;默认 - &gt;红色)。

在模拟器上,一切都很好:默认情况下项目是红色的,当我按下它变为绿色时,当我释放时它变为蓝色。如果我选择另一个项目:先前选择的项目将返回红色,新选择的项目将变为蓝色。

在我的三星设备上:默认情况下,项目为红色,当我按下一个变为绿色时,当我释放时它再次变为红色(即未选中)。

这似乎是三星ListView实现中的一个错误(它是一个自定义实现,因此很难在没有源代码的情况下进行跟踪)。

编辑:不是错误,而是因触摸模式略有不同的行为(请参阅接受回答中的链接)

您对如何解决此错误/ 行为有什么想法吗?

附加约束:我不能使用 xml选择器,因为我收到的颜色只能在运行时使用。

我的设备是三星GT-B5330,API 15.(但我希望它出现在大多数三星设备上)

这是完整的(可编译的)代码

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;
    }
}
}

2 个答案:

答案 0 :(得分:1)

我手边没有三星设备(Galaxy Nexus不算数,它有简单的Android,你的例子也很好用)所以我无法测试我的假设但似乎ListView下降选择的状态项目发布后。您可以使用HierarchyViewer进行检查(如果手机未植根,请使用Romain Guy的ViewServer。)

由于TouchMode依赖于具有触摸屏的选择是危险的(参见http://android-developers.blogspot.ru/2008/12/touch-mode.html)。用两个词来说:当用户与触摸屏交互时,你没有选择(或焦点,顺便说一句)的概念。仿真器通常具有D-pad,因此它的行为可能略有不同。

所以我的建议是使用state_checked代替state_selected。 Android有CheckedTextView可能有所帮助。只需调用ListView的setItemChecked即可。此解决方案还具有很好的属性,可以在配置更改之间保持检查项目位置,并在按下其他项目时自动取消选中先前检查的项目(如果使用CHOICE_MODE_SINGLE)。

如果这是不可接受的,你需要坚持state_selected,那么你可以将TextView包装成LinearLayout,它应该防止选择消失。但是不要忘记,当ListView退出屏幕时,ListView会对其他列表项重复使用相同的视图,因此您需要跟踪适配器中的选择状态以正确设置它。

答案 1 :(得分:0)

我可以确认,我在三星设备(Nexus,S3,Note2)上遇到过类似的错误。 Listview项目具有默认的背景颜色,因此在我的情况下为黑色。但是它会随机变成红色。如果我将listviewitem backgroundcolor显式设置为黑色,我没有遇到该错误。老实说,我不知道如何解决你的情况,但定义所有州的颜色可能对你有帮助。