Android ListView是否保持选中状态?

Android ListView是否保持选中状态?,android,listview,highlight,Android,Listview,Highlight,我有一个充满项目的列表视图,在用户选择一个项目后,它会亮起,然后恢复正常。有没有一种方法可以让用户在我的ListView中选择一个项目时,它保持选中状态并高亮显示?显然,“消失的选择”是出于设计;它是一种叫做“的东西”。我通读了那份文件,仍然不知道他们为什么认为这是个好主意。我的猜测是,由于Android最初是为小屏幕设备设计的,他们希望你在屏幕上填写一个列表,然后当用户单击一个项目时,移动到另一个屏幕上的新列表。因此,用户不会意识到Android丢失了对所选项目的跟踪 但是,例如,如果您希望用

我有一个充满项目的列表视图,在用户选择一个项目后,它会亮起,然后恢复正常。有没有一种方法可以让用户在我的ListView中选择一个项目时,它保持选中状态并高亮显示?

显然,“消失的选择”是出于设计;它是一种叫做“的东西”。我通读了那份文件,仍然不知道他们为什么认为这是个好主意。我的猜测是,由于Android最初是为小屏幕设备设计的,他们希望你在屏幕上填写一个列表,然后当用户单击一个项目时,移动到另一个屏幕上的新列表。因此,用户不会意识到Android丢失了对所选项目的跟踪

但是,例如,如果您希望用户选择一个项目,然后在同一屏幕上显示该项目的信息,那么这种行为非常烦人。如果选择消失了,用户如何知道他们点击了什么(当然假设用户的注意力跨度像金鱼)

一种可能的解决方案是将所有列表项更改为单选按钮。我真的不喜欢那个解决方案,因为它浪费了屏幕空间。我宁愿使用背景色来显示选中的项目。到目前为止,我已经看到了一个解决方案,但它并不完全或通用。因此,我的解决方案如下:

1.在XML布局文件中 转到ListView元素和以下属性:
android:choiceMode=“singleChoice”
。我不完全确定这是做什么的(它本身不允许用户选择任何东西),但是如果没有这个属性,下面的代码就无法工作

2.定义以下类 它用于跟踪所选项目,还允许您在Java中模拟按引用传递:

public class IntHolder {
    public int value;
    public IntHolder() {}
    public IntHolder(int v) { value = v; } 
}
3.把下面的代码放在某个地方 我假设你把它放在你的活动中,但它可以放在任何课堂上,真的:

static void setListItems(Context context, AdapterView listView, List listItems, final IntHolder selectedPosition)
{
    setListItems(context, listView, listItems, selectedPosition, 
                 android.R.layout.simple_list_item_1, 
                 android.R.layout.simple_spinner_dropdown_item);
}
static void setListItems(Context context, AdapterView listView, List listItems, final IntHolder selectedPosition, 
                         int list_item_id, int dropdown_id)
{
    listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        public void onItemClick(AdapterView<?> list, View lv, int position, long id) {
            selectedPosition.value = position;
        }
    });
    ArrayAdapter<CharSequence> adapter = new ArrayAdapter<CharSequence>(context, list_item_id, listItems) { 
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            View itemView = super.getView(position, convertView, parent);
            if (selectedPosition.value == position)
                itemView.setBackgroundColor(0xA0FF8000); // orange
            else
                itemView.setBackgroundColor(Color.TRANSPARENT);
            return itemView;
        }
    };
    adapter.setDropDownViewResource(dropdown_id);
    listView.setAdapter(adapter);
}
就这些!以上假设您想要单一选择。通过对getView()进行一些小的修改,我想您也可以支持多选,但您可能应该使用复选框


警告:此解决方案需要进一步开发。如果用户使用箭头键或按钮选择某个项目,则从IntHolder的角度将而不是选择该项目。如果用户按下未标记的按钮(该按钮的名称是什么?“输入”?),则该项目将被“正式”选中,但随后您会遇到另一个问题,因为如果用户再次使用箭头键,它将有点像选择了两个项目。如果您想知道如何使IntHolder中的“内部选择”与“键盘选择”或其他名称保持同步,请留下评论。它到底叫什么?

ListView中有一个名为listSelector的属性:

Drawable用于指示列表中当前选定的项目


评论后编辑

要确保
列表视图保持选中状态,您应该

① 通过xml或编程方式设置视图的属性
choiceMode

② 使用适配器,该适配器使用实现接口的视图,如(内部布局)

文件
TestActivity.java

public class TestActivity extends Activity {

    private static final int SINGLE_CHOICE = android.R.layout.simple_list_item_single_choice;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.test);

        String[] items = {"test 1", "test 2", "test 3"};
        ListAdapter adapter = new ArrayAdapter<String>(this, SINGLE_CHOICE, items);
        ListView list = (ListView) findViewById(R.id.testList);
        list.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
        list.setAdapter(adapter);
    }
}
公共类测试活动扩展活动{
私有静态final int SINGLE_CHOICE=android.R.layout.simple_list_item_SINGLE_CHOICE;
@凌驾
创建时受保护的void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.test);
字符串[]项={“测试1”、“测试2”、“测试3”};
ListAdapter=new ArrayAdapter(此选项为单选项);
ListView列表=(ListView)findViewById(R.id.testList);
list.setChoiceMode(ListView.CHOICE\u MODE\u SINGLE);
list.setAdapter(适配器);
}
}

这个答案可行,试试这个

@Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long arg3)
    {
        for(int a = 0; a < parent.getChildCount(); a++)
        {
            parent.getChildAt(a).setBackgroundColor(Color.TRANSPARENT);
        }
    view.setBackgroundColor(Color.GREEN);
}
@覆盖
public void onItemClick(AdapterView父视图、视图视图、整型位置、长arg3)
{
对于(int a=0;a
这里有一个比Qwertie更简单的解决方案:

不要依赖给定的选择机制。你自己做吧

View mSelectedItemView = null; //class member variable
View mTouchedItemView = null; //class member variable

ListView v = (ListView) getActivity().findViewById(R.id.listView);
// select on click
v.setOnItemClickListener(new OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView<?> adapter,
            View clickedViewItem, int position, long id) {
        if (mSelectedItemView != null)
            selectedItemView.setBackgroundColor(Color.WHITE);
        clickedViewItem.setBackgroundColor(Color.YELLOW);
        mSelectedItemView = clickedViewItem;
    }
});
// highlight on touch
v.setOnTouchListener(new OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        if (v instanceof ListView) {
            ListView listView = (ListView) v;
            // Find the child view that was touched (perform a
            // hit test)
            Rect rect = new Rect();
            int childCount = listView.getChildCount();
            int[] listViewCoords = new int[2];
            v.getLocationOnScreen(listViewCoords);
            int x = (int) event.getRawX() - listViewCoords[0];
            int y = (int) event.getRawY() - listViewCoords[1];
            View child;
            for (int i = 0; i < childCount; i++) {
                child = listView.getChildAt(i);
                child.getHitRect(rect);
                if (rect.contains(x, y)) {
                    View touchedView = child;
                    if (event.getAction() == MotionEvent.ACTION_DOWN) {
                        touchedView
                                .setBackgroundColor(Color.RED);
                        mTouchedItemView = touchedView;
                    } else if (event.getAction() == MotionEvent.ACTION_UP) {
                        mTouchedItemView 
                                .setBackgroundColor(Color.WHITE);
                    }
                }
            }
        }
        return false;
    }
});
View mSelectedItemView=null//类成员变量
视图mTouchedItemView=null//类成员变量
ListView v=(ListView)getActivity().findViewById(R.id.ListView);
//点击选择
v、 setOnItemClickListener(新的OnItemClickListener(){
@凌驾
公用MClick(适配器视图适配器,
查看单击的视图项,整数位置,长id){
如果(mSelectedItemView!=null)
选择editemview.setBackgroundColor(Color.WHITE);
单击ViewItem.setBackgroundColor(颜色.黄色);
mSelectedItemView=单击的视图项;
}
});
//触摸时突出显示
v、 setOnTouchListener(新的OnTouchListener(){
@凌驾
公共布尔onTouch(视图v,运动事件){
if(ListView的v实例){
ListView ListView=(ListView)v;
//查找被触摸的子视图(执行
//命中测试)
Rect Rect=新的Rect();
int childCount=listView.getChildCount();
int[]listViewCoords=新int[2];
v、 getLocationOnScreen(listViewCoords);
int x=(int)event.getRawX()-listViewCoords[0];
int y=(int)event.getRawY()-listViewCoords[1];
看孩子;
for(int i=0;iView mSelectedItemView = null; //class member variable
View mTouchedItemView = null; //class member variable

ListView v = (ListView) getActivity().findViewById(R.id.listView);
// select on click
v.setOnItemClickListener(new OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView<?> adapter,
            View clickedViewItem, int position, long id) {
        if (mSelectedItemView != null)
            selectedItemView.setBackgroundColor(Color.WHITE);
        clickedViewItem.setBackgroundColor(Color.YELLOW);
        mSelectedItemView = clickedViewItem;
    }
});
// highlight on touch
v.setOnTouchListener(new OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        if (v instanceof ListView) {
            ListView listView = (ListView) v;
            // Find the child view that was touched (perform a
            // hit test)
            Rect rect = new Rect();
            int childCount = listView.getChildCount();
            int[] listViewCoords = new int[2];
            v.getLocationOnScreen(listViewCoords);
            int x = (int) event.getRawX() - listViewCoords[0];
            int y = (int) event.getRawY() - listViewCoords[1];
            View child;
            for (int i = 0; i < childCount; i++) {
                child = listView.getChildAt(i);
                child.getHitRect(rect);
                if (rect.contains(x, y)) {
                    View touchedView = child;
                    if (event.getAction() == MotionEvent.ACTION_DOWN) {
                        touchedView
                                .setBackgroundColor(Color.RED);
                        mTouchedItemView = touchedView;
                    } else if (event.getAction() == MotionEvent.ACTION_UP) {
                        mTouchedItemView 
                                .setBackgroundColor(Color.WHITE);
                    }
                }
            }
        }
        return false;
    }
});
 android:listSelector="@drawable/selector_expandable_listview" 
 android:drawSelectorOnTop="true"
    //SetOnClickListner to catch Events
    listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
         view.setSelected(true);
        }
    });
android:listSelector="@color/my_color"