3

我对三星手机上的简单 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 的项目)使用 a作为ColorStateListtextColor(按下-->绿色;选择-->蓝色;默认-->红色)。

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

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

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

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

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

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

我的设备是 Samsung 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;
    }
}
}
4

2 回答 2

1

我手头没有三星设备(Galaxy Nexus 不算,它有普通的 Android 并且在你的示例中工作得很好)所以我无法测试我的假设,但似乎 ListView 在它之后删除了项目的选定状态已被释放。您可以使用 HierarchyViewer 检查它(如果您的手机没有root,请使用 Romain Guy 的ViewServer )。

由于 TouchMode,依赖具有触摸屏的选择是危险的(请参阅http://android-developers.blogspot.ru/2008/12/touch-mode.html)。简而言之:当用户与触摸屏交互时,您没有选择(或焦点,顺便说一句)的概念。模拟器通常有方向键,所以它的行为可能略有不同。

所以我对你的建议是使用state_checked而不是state_selected. Android 有CheckedTextView可能会有所帮助。只需调用 ListView 的setItemChecked. 该解决方案还具有在配置更改之间保持选中项位置以及在按下其他项(如果CHOICE_MODE_SINGLE使用)时自动取消选中先前选中项的良好属性。

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

于 2013-01-10T16:16:25.217 回答
0

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

于 2013-01-10T15:46:47.967 回答