开源项目MultiChoiceAdapter详解(二)——MultiChoiceArrayAdapter的使用
MultiChoiceArrayAdapter其实就是可以多选的ArrayAdapter了,ArrayAdpter我们已经很熟悉了。MultiChoiceArrayAdapter这个类是抽象类,所以使用前必须要继承。下面是使用MultiChoiceArrayAdapter的步骤:
0.用自定义的控件来写一个layout
1.写一个类来继承MultiChoiceArrayAdapter
2.实例化这个类
3.用setAdapterView()来设置要加载适配器的控件。
4.写上保存的方法
@Override protected void onSaveInstanceState(Bundle outState) { actionModeAdapter.save(outState); }
零、写布局文件
listview_actionmode_layout.xml
没什么特别的,就一个listview
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <ListView android:id="@+id/actionMode_listView" android:layout_width="match_parent" android:layout_height="wrap_content"> </ListView> </LinearLayout>
item.xml
注意这里要用自己定义的实现了Checkable接口的控件
<?xml version="1.0" encoding="utf-8"?> <com.manuelpeinado.multichoiceadapter.view.CheckableLinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/custom_list_item_background" android:orientation="horizontal"> <!-- 上面必须要用自定义的layout,否则不会有选中的效果!!! --> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="16dp" android:orientation="horizontal" > <TextView android:id="@+id/item_textView" android:layout_width="200dp" android:layout_height="wrap_content" android:layout_marginLeft="30dp" android:layout_gravity="center_vertical" android:textColor="#000000" android:layout_weight="1" android:textAppearance="?android:attr/textAppearanceLarge" /> </LinearLayout> </com.manuelpeinado.multichoiceadapter.view.CheckableLinearLayout>
二、继承MultiChoiceAdapter
这个是重点,每个方法中实现了不同的功能。其中discardSelectedItems()是自己写的,用来移除已经选中的items。
注意:onCreateActionMode()必须返回true,否则报错!
private class TestAdapter extends MultiChoiceArrayAdapter<String>{ String tag = getClass().getSimpleName().toString(); /** * @param savedInstanceState * @param context * @param resource:Item的布局文件,即 R.layout.xxx * @param textViewResourceId:显示文字的textview的id,即R.id.xxxx * @param objects:一个String数组 */ public TestAdapter(Bundle savedInstanceState, Context context, int resource, int textViewResourceId, String[] objects) { //为了避免错误,这里将String数组转为ArrayList对象 this(savedInstanceState,context,resource,textViewResourceId, new ArrayList<String>(Arrays.asList(objects))); } /** * @param savedInstanceState * @param context * @param resource:Item的布局文件,即 R.layout.xxx * @param textViewResourceId:显示文字的textview的id,即R.id.xxxx * @param items:一个list<String>对象 */ public TestAdapter(Bundle savedInstanceState, Context context, int resource, int textViewResourceId, List<String> items) { super(savedInstanceState, context, resource, textViewResourceId, items); } /** * 传入actionMode对象,进行设置图标和操作 * 注意要返回true! */ @Override public boolean onCreateActionMode(ActionMode mode, Menu menu) { Log.i(tag, "onCreateActionMode"); MenuInflater inflater = mode.getMenuInflater(); inflater.inflate(R.menu.my_action_mode, menu); //这里必须要写true,否则会报空指针!!! return true; } /** * 进行AndroidMode上图标操作的设置 */ @Override public boolean onActionItemClicked(ActionMode mode, MenuItem item) { if (item.getItemId() == R.id.menu_share) { Toast.makeText(getContext(), "分享了" + getCheckedItemCount()+"个item", Toast.LENGTH_SHORT).show(); return true; } if (item.getItemId() == R.id.menu_discard) { //丢弃选中的items discardSelectedItems(); return true; } return false; } @Override public boolean onPrepareActionMode(ActionMode arg0, Menu arg1) { Log.i(tag, "onPrepareActionMode"); return false; } /** * (非必须) * 设置点击、选中效果,非必须。如果你在item的layout设置了 android:background那么下面就不用进行设置背景了 * 个人推荐在item的layout中设置背景色,example:android:background="@drawable/custom_list_item_background" */ /*@Override protected View getViewImpl(int position, View convertView, ViewGroup parent) { //Log.i(tag, "getViewImpl"); View view = super.getViewImpl(position, convertView, parent); view.setBackgroundResource(R.drawable.custom_list_item_background); return view; }*/ /** * 从适配器中移除某些item */ private void discardSelectedItems() { //得到选中的items Set<Long> selection = getCheckedItems(); String[] items = new String[selection.size()]; int i = 0; for (long position : selection) { items[i++] = getItem((int)position); } //通过判断名字来remove掉这些items for (String item : items) { /** * 这里用remove时要注意传入适配器的不能是String[] items对象。否则会报错 * 这里我已经在构造函数中进行了处理,传入String数组也不会出错了~ */ remove(item); } finishActionMode(); } }
这里在继承的时候其实就顺带实现了ActionMode的callback接口的内容了,如果对ActionMode熟悉的人一定很容易理解。
二、实例化这个类
TestAdapter actionModeAdapter;
String[] data = {"android","ios","wp","c++", "java","c#","javascript","vb", "delphi","PB","ASP","SQL"}; ListView actionModelistView = (ListView)findViewById(R.id.actionMode_listView); actionModeAdapter = new TestAdapter(savedInstanceState, this,R.layout.item, R.id.item_textView, data);
三、设置控件和监听器
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.listview_actionmode_layout); String[] data = {"android","ios","wp","c++", "java","c#","javascript","vb", "delphi","PB","ASP","SQL"}; ListView actionModelistView = (ListView)findViewById(R.id.actionMode_listView); actionModeAdapter = new TestAdapter(savedInstanceState, this,R.layout.item, R.id.item_textView, data); actionModeAdapter.setAdapterView(actionModelistView); actionModeAdapter.setOnItemClickListener(new MyItemClick(actionModeAdapter)); //listView.setAdapter(adapter);//不这么用啦 } /** * @author:Jack Tony * @tips :点击事件的监听器 * @date :2014-10-20 */ private class MyItemClick implements OnItemClickListener{ private TestAdapter mAdapter; public MyItemClick(TestAdapter adapter) { mAdapter = adapter; } @Override public void onItemClick(AdapterView<?> arg0, View arg1, int position, long arg3) { Toast.makeText(getApplicationContext(), "点击了: " + mAdapter.getItem(position), Toast.LENGTH_SHORT).show(); } }
四、保存的方法
@Override protected void onSaveInstanceState(Bundle outState) { actionModeAdapter.save(outState); }
于是大功告成!下面是全部代码:
ArrayAdapterTestActivity.java (这个类没用兼容模式,如果用兼容模式请参考顶部的注释,其实就是导入不同的包即可)
package com.kale.multichoiceadaptertest; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Set; import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.util.Log; import android.view.ActionMode; 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.Toast; import com.manuelpeinado.multichoiceadapter.normal.MultiChoiceArrayAdapter; /** * 如果是4.0以上的版本可以直接用activity,不用actionbarActivity,导入的时候导入 * import android.view.ActionMode; * import com.manuelpeinado.multichoiceadapter.normal.MultiChoiceArrayAdapter; * 把 * import android.support.v7.view.ActionMode; * import com.manuelpeinado.multichoiceadapter.compat.MultiChoiceArrayAdapter; * 删掉 */ /** * @author:Jack Tony * @tips :ActionMode和ArrayAdapter配合实现多选 * @date :2014-10-21 */ public class ArrayAdapterTestActivity extends Activity{ TestAdapter actionModeAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.listview_actionmode_layout); String[] data = {"android","ios","wp","c++", "java","c#","javascript","vb", "delphi","PB","ASP","SQL"}; ListView actionModelistView = (ListView)findViewById(R.id.actionMode_listView); actionModeAdapter = new TestAdapter(savedInstanceState, this,R.layout.item, R.id.item_textView, data); actionModeAdapter.setAdapterView(actionModelistView); actionModeAdapter.setOnItemClickListener(new MyItemClick(actionModeAdapter)); //listView.setAdapter(adapter);//不这么用啦 } @Override protected void onSaveInstanceState(Bundle outState) { actionModeAdapter.save(outState); } private class TestAdapter extends MultiChoiceArrayAdapter<String>{ String tag = getClass().getSimpleName().toString(); /** * @param savedInstanceState * @param context * @param resource:Item的布局文件,即 R.layout.xxx * @param textViewResourceId:显示文字的textview的id,即R.id.xxxx * @param objects:一个String数组 */ public TestAdapter(Bundle savedInstanceState, Context context, int resource, int textViewResourceId, String[] objects) { //为了避免错误,这里将String数组转为ArrayList对象 this(savedInstanceState,context,resource,textViewResourceId, new ArrayList<String>(Arrays.asList(objects))); } /** * @param savedInstanceState * @param context * @param resource:Item的布局文件,即 R.layout.xxx * @param textViewResourceId:显示文字的textview的id,即R.id.xxxx * @param items:一个list<String>对象 */ public TestAdapter(Bundle savedInstanceState, Context context, int resource, int textViewResourceId, List<String> items) { super(savedInstanceState, context, resource, textViewResourceId, items); } /** * 传入actionMode对象,进行设置图标和操作 * 注意要返回true! */ @Override public boolean onCreateActionMode(ActionMode mode, Menu menu) { Log.i(tag, "onCreateActionMode"); MenuInflater inflater = mode.getMenuInflater(); inflater.inflate(R.menu.my_action_mode, menu); //这里必须要写true,否则会报空指针!!! return true; } /** * 进行AndroidMode上图标操作的设置 */ @Override public boolean onActionItemClicked(ActionMode mode, MenuItem item) { if (item.getItemId() == R.id.menu_share) { Toast.makeText(getContext(), "分享了" + getCheckedItemCount()+"个item", Toast.LENGTH_SHORT).show(); return true; } if (item.getItemId() == R.id.menu_discard) { //丢弃选中的items discardSelectedItems(); return true; } return false; } @Override public boolean onPrepareActionMode(ActionMode arg0, Menu arg1) { Log.i(tag, "onPrepareActionMode"); return false; } /** * (非必须) * 设置点击、选中效果,非必须。如果你在item的layout设置了 android:background那么下面就不用进行设置背景了 * 个人推荐在item的layout中设置背景色,example:android:background="@drawable/custom_list_item_background" */ /*@Override protected View getViewImpl(int position, View convertView, ViewGroup parent) { //Log.i(tag, "getViewImpl"); View view = super.getViewImpl(position, convertView, parent); view.setBackgroundResource(R.drawable.custom_list_item_background); return view; }*/ /** * 从适配器中移除某些item */ private void discardSelectedItems() { //得到选中的items Set<Long> selection = getCheckedItems(); String[] items = new String[selection.size()]; int i = 0; for (long position : selection) { items[i++] = getItem((int)position); } //通过判断名字来remove掉这些items for (String item : items) { /** * 这里用remove时要注意传入适配器的不能是String[] items对象。否则会报错 * 这里我已经在构造函数中进行了处理,传入String数组也不会出错了~ */ remove(item); } finishActionMode(); } } /** * @author:Jack Tony * @tips :点击事件的监听器 * @date :2014-10-20 */ private class MyItemClick implements OnItemClickListener{ private TestAdapter mAdapter; public MyItemClick(TestAdapter adapter) { mAdapter = adapter; } @Override public void onItemClick(AdapterView<?> arg0, View arg1, int position, long arg3) { Toast.makeText(getApplicationContext(), "点击了: " + mAdapter.getItem(position), Toast.LENGTH_SHORT).show(); } } }
开源项目MultiChoiceAdapter详解(一)——概要介绍
开源项目MultiChoiceAdapter详解(二)——MultiChoiceArrayAdapter的使用
开源项目MultiChoiceAdapter详解(三)——MulitChoiceNormalArrayAdapter的使用
开源项目MultiChoiceAdapter详解(四)——MultiChoiceBaseAdapter的使用
开源项目MultiChoiceAdapter详解(五)——可扩展的MultiChoiceBaseAdapter
开源项目MultiChoiceAdapter详解(六)——GridView和MultiChoiceBaseAdapter配合使用