您的位置:首页 > 其它

ListView 选择模式

2016-04-23 17:30 405 查看
实际的应用APP开发中,基本上由自己来控制多选的逻辑,后来参考大神的作品,发现ListView本身已经实现了,下面就跟随我的足迹,一起探讨一下吧。

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;


AbsListView对多选的支持

/**
* 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 <code>false</code> 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).
*
* <p>To determine the specific items that are currently selected, use one of
* the <code>getChecked*</code> 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;

import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.support.v4.content.res.ResourcesCompat;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;

@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
public class MyAdapter extends BaseAdapter {
private Context mContext;
private ListView mListView;
private Drawable mUnCheckedDrawable;
private Drawable mCheckedDrawable;

private String[] mStrings = { "Abbaye de Belloc",
"Abbaye du Mont des Cats", "Abertam", "Anthoriro" };

public MyAdapter(Context context, ListView list) {
mContext = context;
mListView = list;
mCheckedDrawable = ResourcesCompat.getDrawable(context.getResources(),
R.drawable.list_selected_holo_light, null);
mUnCheckedDrawable = ResourcesCompat.getDrawable(
context.getResources(),
R.drawable.conversation_item_background_read, null);
}

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]);

int sdk = android.os.Build.VERSION.SDK_INT;

if (mListView.isItemChecked(position)) {
if (sdk < android.os.Build.VERSION_CODES.JELLY_BEAN) {
tv.setBackgroundDrawable(mCheckedDrawable);
} else {
tv.setBackground(mCheckedDrawable);
}
} else {
if (sdk < android.os.Build.VERSION_CODES.JELLY_BEAN) {
tv.setBackgroundDrawable(mUnCheckedDrawable);
} else {
tv.setBackground(mUnCheckedDrawable);
}
}

return tv;
}

}


ListView.CHOICE_MODE_MULTIPLE

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啦!

ListView.CHOICE_MODE_MULTIPLE_MODAL

该模式在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退出多选模式。

ListView.CHOICE_MODE_SINGLE

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


ListView.CHOICE_MODE_NONE

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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: