ListView自带单选和多选的特技Choice Mode

来源:互联网 发布:哥白尼式革命 知乎 编辑:程序博客网 时间:2024/05/18 01:07

ListView本身带有单选和多选功能,也就是说在单选模式下,它能够记住当前选中的唯一的列表项;在多选模式下,它能够记住目前选取的所有的列表项。

这种选择模式共有4种CHOICE_MODE_NONE CHOICE_MODE_SINGLE CHOICE_MODE_MULTIPLE CHOICE_MODE_MULTIPLE_MODAL

使用setChoiceMode()函数,就可以设置ListView的选择模式。

ListView lv = (ListView) findViewById(R.id.list_view);lv.setChoiceMode(ListView.CHOICE_MODE_NONE);
  • 1
  • 2
  • 1
  • 2

9.4.1 CHOICE_MODE_NONE

这是ListView默认的选择模式,当使用者点击列表项后,不会将任何点击的列表项当成被选择上的列表项。

9.4.2 CHOICE_MODE_SINGLE

使用这个选项模式,当使用者点击列表项后,会将最后一次点击的列表项当成被选择上的列表项。

ArrayAdapter adapter = new ArrayAdapter<String>(this,                 android.R.layout.simple_list_item_single_choice , datalist);lv.setChoiceMode(ListView.CHOICE_MODE_SINGLE);lv.setAdapter(adapter);
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

每次点击列表项,可以在它的监听函数中得知哪个列表项被点击了,

lv.setOnItemClickListener(new ListView.OnItemClickListener() {    @Override    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {        //添加需要响应的操作    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

以后就可以通过ListViewgetCheckedItemPositions()获取被选中的数据项的位置列表,

SparseBooleanArray checkedItems = lv.getCheckedItemPositions();
  • 1
  • 1

例如,当列表项按照序号为3->2->1-7的顺序被点击后,7将被记录下来,作为当前被选中的数据项。调用getCheckedItemPositions()后,将得到一个键值对,里面只会记录,

key=7, value=true
  • 1
  • 1

这里为了看到被选中的效果,采用了Android SDK提供的android.R.layout.simple_list_item_single_choice布局,作为列表项的布局。

9.4.3 CHOICE_MODE_MULTIPLE

使用这个选项模式,当使用者点击列表项后,会将所有点击的列表项当成被选择上的列表项。

ArrayAdapter adapter = new ArrayAdapter<String>(this,                 android.R.layout.simple_list_item_multiple_choice, datalist);lv.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);lv.setAdapter(adapter);
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

每次点击列表项,可以在它的监听函数中得知哪个列表项被点击了,

lv.setOnItemClickListener(new ListView.OnItemClickListener() {    @Override    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {        //添加需要响应的操作    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

通过ListViewgetCheckedItemPositions()获取被选中的数据项的位置列表,

SparseBooleanArray checkedItems = lv.getCheckedItemPositions();
  • 1
  • 1

例如,当列表项按照序号为3->2->1->7的顺序被点击后,3 2 1 7将被记录下来,作为当前被选中的数据项。调用getCheckedItemPositions()后,将得到一个个键值对,里面会记录,

key=1, value=truekey=2, value=truekey=3, value=truekey=7, value=true
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

这些记录,将按照列表项的位置从小到大排列。

如果用户在已经被选上的数据项上,又再次点击,这将取消对它的选择。例如,当列表项按照序号为3->2->1->7->2->1的顺序被点击后,就变成了,

key=1, value=falsekey=2, value=falsekey=3, value=truekey=7, value=true
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

对于被取消了选择的列表项,并不会从记录中移除,而是改变它的值成false

这里为了看到被选中的效果,采用了Android SDK提供的android.R.layout.simple_list_item_multiple_choice布局,作为列表项的布局。

9.4.4 CHOICE_MODE_MULTIPLE_MODAL

CHOICE_MODE_MULTIPLE_MODAL模式中,用户必须通过长按任意一个列表项,进入多选模式,否则不能进行多选。

这个模式的使用与CHOICE_MODE_MULTIPLE类似,不过它需要设置一个ActionMode,这样才能在长按列表项后,改变ActionBar的菜单栏,打开多选的菜单。

  1. 实现ListViewMultiChoiceModeListener接口,

    private class MyMultiChoiceModeListener implements ListView.MultiChoiceModeListener {    @Override    public void onItemCheckedStateChanged(ActionMode mode, int position, long id, boolean checked) {        //添加列表项被点击后的响应    }    @Override    public boolean onCreateActionMode(ActionMode mode, Menu menu) {        //这里返回true        return true;    }    @Override    public boolean onPrepareActionMode(ActionMode mode, Menu menu) {        //这里返回true        return true;    }    @Override    public boolean onActionItemClicked(ActionMode mode, MenuItem item) {        //这里返回true        return true;    }    @Override    public void onDestroyActionMode(ActionMode mode) {    }}
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
  2. 使用创建的接口,传递给ListView

    ArrayAdapter adapter = new ArrayAdapter<String>(this,                 android.R.layout.simple_list_item_multiple_choice, datalist);lv.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);ListView.MultiChoiceModeListener callback = new MyMultiChoiceModeListener();lv.setMultiChoiceModeListener(callback);lv.setAdapter(adapter);
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

CHOICE_MODE_MULTIPLE_MODAL模式下,对列表项的点击,是在ListView.MultiChoiceModeListeneronItemCheckedStateChanged()函数中响应的。

这里为了看到被选中的效果,采用了Android SDK提供的android.R.layout.simple_list_item_multiple_choice布局,作为列表项的布局。

9.4.5 关于单选和多选的状态背景

前面的演示中,分别对不同的选择模式,使用了不同的数据项布局,

CHOICE_MODE_SINGLE         --> android.R.layout.simple_list_item_single_choiceCHOICE_MODE_MULTIPLE       --> android.R.layout.simple_list_item_multiple_choiceCHOICE_MODE_MULTIPLE_MODAL --> android.R.layout.simple_list_item_multiple_choice
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

我们也可以选择自己的布局来实现。但是不管使用什么布局,我们都希望被选上的列表项有特别的效果,和其他没有被选上的数据项区别开。这里有两种方案,

  1. 使用实现了Clickable接口的控件或者布局,作为数据项的布局。例如前面我们使用的android.R.layout.simple_list_item_multiple_choiceandroid.R.layout.simple_list_item_single_choice等,它们本身就是CheckedTextView。当点击它们的时候,它们就自带了勾选框,可以看到效果。

    所以,可以选择CheckBox Switch这类同样实现了Clickable接口的布局来表现;也可以自定义一个实现了Clickable接口的布局。这里用android.R.layout.simple_list_item_multiple_choice的实现来举个例子,

    <CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android"    android:id="@android:id/text1"    android:layout_width="match_parent"    android:layout_height="?android:attr/listPreferredItemHeightSmall"    android:textAppearance="?android:attr/textAppearanceListItemSmall"    android:gravity="center_vertical"    android:checkMark="?android:attr/listChoiceIndicatorMultiple"    android:paddingStart="?android:attr/listPreferredItemPaddingStart"    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd" />
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
  2. 给数据项的布局使用一个Selector,告诉这个布局,当它被activated以后要怎么显示。比如,定义一个布局custom_item_layout.xml,

    <TextView xmlns:android="http://schemas.android.com/apk/res/android"    android:id="@android:id/text1"    android:layout_width="match_parent"    android:layout_height="wrap_content"    android:minHeight="48dp" --> 为了布局好看设置一个最小高度    android:gravity="center_vertical"    android:padding="5dp"    android:background="@drawable/selector"></TextView>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    给这个布局设计一个selector,增加对android:activated属性的设置,

    <selector xmlns:android="http://schemas.android.com/apk/res/android">    <item android:state_activated="true" android:drawable="@color/yellow"/></selector>
    • 1
    • 2
    • 3
    • 1
    • 2
    • 3

    使用这个这个布局,

    ArrayAdapter adapter = new ArrayAdapter<String>(this,                 R.layout.custom_item_layout, datalist);lv.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);lv.setAdapter(adapter);
    • 1
    • 2
    • 3
    • 4
    • 1
    • 2
    • 3
    • 4

    当我们多选的时候,那些选中项,就变成黄色,看到如下的界面,


0 0
原创粉丝点击