实际的应用APP开发中,基本上由自己来控制多选的逻辑,后来参考大神的作品,发现ListView本身已经实现了,下面就跟随我的足迹,一起探讨一下吧。
/**
* Normal list that does not indicate choices
*/
public static final int CHOICE_MODE_NONE = 0;
/**
* The list allows up to one choice
*/
public static final int CHOICE_MODE_SINGLE = 1;
/**
* The list allows multiple choices
*/
public static final int CHOICE_MODE_MULTIPLE = 2;
/**
* The list allows multiple choices in a modal selection mode
*/
public static final int CHOICE_MODE_MULTIPLE_MODAL = 3;
/**
* Returns the checked state of the specified position. The result is only
* valid if the choice mode has been set to {@link #CHOICE_MODE_SINGLE}
* or {@link #CHOICE_MODE_MULTIPLE}.
*
* @param position The item whose checked state to return
* @return The item's checked state or false
if choice mode
* is invalid
*
* @see #setChoiceMode(int)
*/
public boolean isItemChecked(int position) {
if (mChoiceMode != CHOICE_MODE_NONE && mCheckStates != null) {
return mCheckStates.get(position);
}
return false;
}
/**
* Returns the number of items currently selected. This will only be valid
* if the choice mode is not {@link #CHOICE_MODE_NONE} (default).
*
* To determine the specific items that are currently selected, use one of
* the getChecked*
methods.
*
* @return The number of items currently selected
*
* @see #getCheckedItemPosition()
* @see #getCheckedItemPositions()
* @see #getCheckedItemIds()
*/
public int getCheckedItemCount() {
return mCheckedItemCount;
}
/**
* Sets the checked state of the specified position. The is only valid if
* the choice mode has been set to {@link #CHOICE_MODE_SINGLE} or
* {@link #CHOICE_MODE_MULTIPLE}.
*
* @param position The item whose checked state is to be checked
* @param value The new checked state for the item
*/
public void setItemChecked(int position, boolean value) {
if (mChoiceMode == CHOICE_MODE_NONE) {
return;
}
...
/**
* Clear any choices previously set
*/
public void clearChoices() {
if (mCheckStates != null) {
mCheckStates.clear();
}
if (mCheckedIdStates != null) {
mCheckedIdStates.clear();
}
mCheckedItemCount = 0;
}
由于本人现在水平比较低,就不讲理论了免得误人子弟,下面讲述一下他们的用法吧,让大家有一个感性的认识。
为了突出关键代码,咱们将所有模式都用到的材料在这里定义一下。
MyAdapter.java
package com.example.listmultichoise;
package com.scott.crash;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;
public class MyAdapter extends BaseAdapter {
private Context mContext;
private ListView mListView;
private String[] mStrings = {"Abbaye de Belloc",
"Abbaye du Mont des Cats", "Abertam", "Anthoriro"};
public MyAdapter(Context context, ListView list) {
mContext = context;
mListView = list;
}
public int getCount() {
return mStrings.length;
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
@SuppressWarnings("deprecation")
public View getView(int position, View convertView, ViewGroup parent) {
TextView tv;
if (convertView == null) {
tv = (TextView) LayoutInflater.from(mContext).inflate(
android.R.layout.simple_expandable_list_item_1, parent,
false);
} else {
tv = (TextView) convertView;
}
tv.setText(mStrings[position]);
if (mListView.isItemChecked(position)) {
tv.setBackgroundResource(android.R.color.holo_red_dark);
} else {
tv.setBackgroundResource(android.R.color.white);
}
return tv;
}
}
package com.example.listmultichoise;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
public class ChoiceModeMultipleActivity extends Activity {
ListView mListView = null;
MyAdapter mAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mListView = new ListView(this);
setContentView(mListView);
mAdapter = new MyAdapter(this, mListView);
mListView.setAdapter(mAdapter);
// 设置为多选模式
mListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
mListView.setOnItemClickListener(new OnItemClickListener() {
// 用户在选择的时候,也会调用该方法,在该方法中调用notifyDataSetChanged刷新选中状态
public void onItemClick(AdapterView> parent, View view,
int position, long id) {
mAdapter.notifyDataSetChanged();
}
});
}
}
在这里强调一下:该模式下,用户选择任意一项后,界面不会自动刷新(这里也就是不会将选中的项自动设置为选中项的颜色),用户点击任意一项会同时触发onItemClick,在这里面刷新界面就ok了。最后要获取所有数据的时候,使用getCheckedItemPositions()就ok啦!
该模式在Android3.0(APIs 11)引入,逻辑有点复杂。多选和onItemClick不能同时触发。CHOICE_MODE_MULTIPLE_MODAL结合actionmode,当启动actionmode(不能在activity中调用startActionMode)时进入多选状态,退出/未进入就是普通的点击行为(即仅仅调用onItemClick)。
当长按item 或者是主动调用setItemChecked方法mChoiceActionMode将被实例化,进入actionmode状态。为了让ListView自动进入多选状态,可以通过以下方法,进入多选状态而不选中任何一项。
if(item.getItemId() == R.id.action_choice){
mListView.setItemChecked(0,true);
mListView.clearChoices();
}
list_multi_select_actionbar.xml 标题栏布局文件
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/custom_title_root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<TextView
android:id="@+id/title"
android:maxLines="1"
android:singleLine="true"
android:layout_gravity="center_vertical"
android:layout_centerVertical="true"
android:textAppearance="?android:attr/textAppearanceMediumInverse"
android:layout_weight="1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/selected_conv_count"
android:maxLines="1"
android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textColor="#ccffffff"
android:layout_gravity="center_vertical"
android:paddingRight="10dip"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
LinearLayout>
用到的几个参数
<string name="action_settings">多选string>
<string name="select_item">已选择:string>
<string name="action_select_all">全选string>
<string name="action_deselect_all">全不选string>
Java代码:
package com.example.listmultichoise;
import android.app.Activity;
import android.os.Bundle;
import android.view.ActionMode;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
public class ChoiceModeMultipleModalActivity extends Activity {
ListView mListView = null;
MyAdapter mAdapter;
ModeCallback mCallback;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mListView = new ListView(this);
setContentView(mListView);
mAdapter = new MyAdapter(this, mListView);
mListView.setAdapter(mAdapter);
mCallback = new ModeCallback();
mListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
mListView.setMultiChoiceModeListener(mCallback);
mListView.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView> parent, View view,
int position, long id) {
Toast.makeText(ChoiceModeMultipleModalActivity.this,
"" + position, Toast.LENGTH_LONG).show();
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.action_choice) {
mListView.setItemChecked(0, true);
mListView.clearChoices();
mCallback.updateSeletedCount();
}
return super.onOptionsItemSelected(item);
}
private class ModeCallback implements ListView.MultiChoiceModeListener {
private View mMultiSelectActionBarView;
private TextView mSelectedCount;
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.multi_select_menu, menu);
if (mMultiSelectActionBarView == null) {
mMultiSelectActionBarView = LayoutInflater.from(
ChoiceModeMultipleModalActivity.this).inflate(
R.layout.list_multi_select_actionbar, null);
mSelectedCount = (TextView) mMultiSelectActionBarView
.findViewById(R.id.selected_conv_count);
}
mode.setCustomView(mMultiSelectActionBarView);
((TextView) mMultiSelectActionBarView.findViewById(R.id.title))
.setText(R.string.select_item);
return true;
}
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
MenuItem mItem = menu.findItem(R.id.action_slelect);
if (mListView.getCheckedItemCount() == mAdapter.getCount()) {
mItem.setTitle(R.string.action_deselect_all);
} else {
mItem.setTitle(R.string.action_select_all);
}
return true;
}
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
switch (item.getItemId()) {
case R.id.action_slelect:
if (mListView.getCheckedItemCount() == mAdapter.getCount()) {
unSelectedAll();
} else {
selectedAll();
}
mAdapter.notifyDataSetChanged();
break;
default:
break;
}
return true;
}
@Override
public void onDestroyActionMode(ActionMode mode) {
mListView.clearChoices();
}
@Override
public void onItemCheckedStateChanged(ActionMode mode, int position,
long id, boolean checked) {
updateSeletedCount();
mode.invalidate();
mAdapter.notifyDataSetChanged();
}
public void updateSeletedCount() {
mSelectedCount.setText(Integer.toString(mListView
.getCheckedItemCount()));
}
}
public void selectedAll() {
for (int i = 0; i < mAdapter.getCount(); i++) {
mListView.setItemChecked(i, true);
}
mCallback.updateSeletedCount();
}
public void unSelectedAll() {
mListView.clearChoices();
mListView.setItemChecked(0, false);
mCallback.updateSeletedCount();
}
}
这里有几个问题需要注意一下:
1.进入页面没有点击标题栏的时候,点击ListView任意一项仅仅是点击——onItemClick会调用;
2.点击标题栏“更多”->“多选”后,调用onOptionsItemSelected方法
mListView.setItemChecked(0, true);
mListView.clearChoices();
ListView进入多选模式;
3.ListView进入多选模式后,调用onCreateActionMode创建新的标题栏;
4.ListView.MultiChoiceModeListener onCreateActionMode/onPrepareActionMode/onOptionsItemSelected和Activity的onCreateOptionsMenu/onPrepareOptionsMenu/onActionItemClicked用法一样。
5.
public void unSelectedAll() {
mListView.clearChoices();
mListView.setItemChecked(0, false);
mCallback.updateSeletedCount();
}
中, mListView.setItemChecked(0, false);和onOptionsItemSelected中mListView.setItemChecked(0, true);遥相呼应,ListView退出多选模式。
package com.example.listmultichoise;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView;
import android.widget.ListView;
public class ChoiceModeSingleActivity extends Activity implements
OnItemClickListener {
private ListView listView;
private MyAdapter adapter;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
listView = new ListView(this);
setContentView(listView);
adapter = new MyAdapter(this, listView);
listView.setAdapter(adapter);
listView.setOnItemClickListener(this);
listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
}
@Override
public void onItemClick(AdapterView> parent, View view, int position,
long id) {
adapter.notifyDataSetChanged();
int checkedPosition = listView.getCheckedItemPosition();
System.err.println();
}
}
package com.example.listmultichoise;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.Toast;
public class ChoiceModeNoneActivity extends Activity implements
OnItemClickListener {
private ListView listView;
private MyAdapter adapter;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
listView = new ListView(this);
setContentView(listView);
adapter = new MyAdapter(this, listView);
listView.setAdapter(adapter);
listView.setOnItemClickListener(this);
// 这个是默认模式,写不写无所谓
listView.setChoiceMode(ListView.CHOICE_MODE_NONE);
}
@Override
public void onItemClick(AdapterView> parent, View view, int position,
long id) {
Toast.makeText(this, position + "", Toast.LENGTH_LONG).show();
}
}
本文核心内容参考地址:
http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/1105/1906.html
Demo下载地址:
http://download.csdn.net/detail/guchuanhang/9500350