Android ListView长按多选模式
来源:互联网 发布:苹果打开数据的快捷键 编辑:程序博客网 时间:2024/06/08 10:31
辛苦堆砌,转载请注明出处,谢谢!
本文示例实现ListView长按条目进入Action Mode,然后可以进行多选,并将选择的条目提前。功能和例子很简单,为的是更好的说明如何实现。
先看一下我们的Activity布局,activity_main.xml
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.yjp.listviewmultiplechoicemodaldemo.MainActivity"> <ListView android:id="@+id/list_view" android:layout_width="match_parent" android:layout_height="match_parent" android:choiceMode="multipleChoiceModal"/></RelativeLayout>重点在于ListView的android:choiceMode属性,置为了mutipleChoiceModal模式。
然后是item的布局item_with_check_box.xml,也很简单
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingTop="5dp" android:paddingBottom="5dp"> <TextView android:id="@+id/text_view" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAppearance="?android:textAppearanceLarge" /> <CheckBox android:id="@+id/selected_check_box" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:clickable="false" android:focusable="false" android:visibility="invisible"/></RelativeLayout>
CheckBox默认不可见,后面我们会看到,只有进入Action Mode时才会显示,我们关注的重点在于CheckBox的clickable和focusable属性都是false,这样可以避免界面响应CheckBox的点击事件,这就避免了我们手动点击CheckBox导致的勾选,大家或许有疑问,这样不对吗?在正常情况下使用,的确是对的,但是由于ListView会重复利用ItemView,所以我们如果靠我们自己记录ItemView中的CheckBox的状态就会出现问题,我们无法知道我们自己维护的CheckBox是否已经重复使用。如果想测试,大家可以自己做个试验,做一个ListView,每个条目中有一个CheckBox,不要置clickable和focusable属性为false,条目多一些,保证一个屏幕放置不下,这时候你先滚动到最底下,然后手动点击CheckBox,然后来回滚动ListView,你会发现,之前勾选的会消失。
当然,如果你乐意,可以维护CheeckBox的勾选状态,但是这样实在是太费劲了,反正我是不乐意。
接下来,还有两个xml文件,一个是我们进入到Action Mode时的Action Bar布局action_mode_bar.xml,如下所示
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAppearance="?android:textAppearanceMediumInverse"/></LinearLayout>有一个TextView,用来显示我们希望显示的内容,这里显示“已选择 X 项”。最后一个xml是一个menu,check_task_priority.xml,作为Action Mode的menu使用。
<?xml version="1.0" encoding="utf-8"?><menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <item android:id="@+id/cancel" android:title="取消" app:showAsAction="always"/> <item android:id="@+id/up" android:title="提前" app:showAsAction="always"/></menu>
下面是我们的MainActivity
package com.yjp.listviewmultiplechoicemodaldemo;import android.annotation.SuppressLint;import android.content.Context;import android.support.annotation.LayoutRes;import android.support.annotation.NonNull;import android.support.annotation.Nullable;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.view.ActionMode;import android.view.LayoutInflater;import android.view.Menu;import android.view.MenuItem;import android.view.View;import android.view.ViewGroup;import android.widget.AbsListView;import android.widget.AdapterView;import android.widget.ArrayAdapter;import android.widget.CheckBox;import android.widget.ListView;import android.widget.TextView;import android.widget.Toast;import java.util.ArrayList;import java.util.Collections;import java.util.List;public class MainActivity extends AppCompatActivity { private CheckListViewAdapter mAdapter; private List<Integer> mItems = new ArrayList<>(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ListView listView = (ListView) findViewById(R.id.list_view); mAdapter = new CheckListViewAdapter(this, R.layout.item_with_check_box, mItems); listView.setAdapter(mAdapter); listView.setMultiChoiceModeListener(new MultiChoiceModeListener(listView)); listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Toast.makeText(MainActivity.this, "点击条目", Toast.LENGTH_SHORT).show(); } }); } @Override protected void onStart() { super.onStart(); mItems.addAll(getItems()); mAdapter.notifyDataSetChanged(); } @Override protected void onStop() { super.onStop(); mItems.clear(); } private List<Integer> getItems() { List<Integer> items = new ArrayList<>(); for (int i = 0; i < 20; i++) { items.add(i); } return items; } private class MultiChoiceModeListener implements AbsListView.MultiChoiceModeListener { private ListView mListView; private TextView mTitleTextView; private List<Integer> mSelectedItems = new ArrayList<>(); private MultiChoiceModeListener(ListView listView) { mListView = listView; } @Override public void onItemCheckedStateChanged(ActionMode mode, int position, long id, boolean checked) { mSelectedItems.add(mAdapter.getItem(position)); mTitleTextView.setText("已选择 " + mListView.getCheckedItemCount() + " 项"); mAdapter.notifyDataSetChanged(); } @Override public boolean onCreateActionMode(ActionMode mode, Menu menu) { mode.getMenuInflater().inflate(R.menu.check_task_priority, menu); @SuppressLint("InflateParams") View multiSelectActionBarView = LayoutInflater.from(MainActivity.this) .inflate(R.layout.action_mode_bar, null); mode.setCustomView(multiSelectActionBarView); mTitleTextView = (TextView)multiSelectActionBarView.findViewById(R.id.title); mTitleTextView.setText("已选择 0 项"); mAdapter.setCheckable(true); mAdapter.notifyDataSetChanged(); return true; } @Override public boolean onPrepareActionMode(ActionMode mode, Menu menu) { return false; } @Override public boolean onActionItemClicked(ActionMode mode, MenuItem item) { switch (item.getItemId()) { case R.id.cancel: break; case R.id.up: Collections.sort(mSelectedItems); for (Integer selectedItem : mSelectedItems) { mItems.remove(selectedItem); } mItems.addAll(0, mSelectedItems); break; default: break; } mode.finish(); return true; } @Override public void onDestroyActionMode(ActionMode mode) { mSelectedItems.clear(); mAdapter.setCheckable(false); mAdapter.notifyDataSetChanged(); } } private class CheckListViewAdapter extends ArrayAdapter<Integer> { private boolean mCheckable; private CheckListViewAdapter(@NonNull Context context, @LayoutRes int resource, @NonNull List<Integer> objects) { super(context, resource, objects); } @NonNull @Override public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) { ViewHolder holder; if (null == convertView) { convertView = LayoutInflater.from(getContext()) .inflate(R.layout.item_with_check_box, parent, false); holder = new ViewHolder(); holder.textView = (TextView) convertView.findViewById(R.id.text_view); holder.checkBox = (CheckBox) convertView.findViewById(R.id.selected_check_box); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } Integer item = getItem(position); if (item != null) { holder.textView.setText(item.toString()); } //可见性和选中状态 if (mCheckable) { holder.checkBox.setVisibility(View.VISIBLE); } else { holder.checkBox.setVisibility(View.INVISIBLE); } holder.checkBox.setChecked(((ListView) parent).isItemChecked(position)); return convertView; } //用来设置是否CheckBox可见 private void setCheckable(boolean checkable) { mCheckable = checkable; } private class ViewHolder { private TextView textView; private CheckBox checkBox; } }}上面的代码中最关键的是要看到我们经常会调用notifyDataSetChanged(),原因在于我们在getView时会按照ListView记录的对应position的选择状态设置我们CheckBox的勾选状态,这样,我们就利用了ListView记录的选择状态,而不需要我们自己维护状态。上面的代码其他部分不难理解,可以运行之后自己试试。
- Android ListView长按多选模式
- Android ListView观察者模式浅析
- Android 自定义ListView系列之适配器模式
- Android ListView – Holder模式和getItemViewType
- Android源码之ListView的适配器模式
- Android源码之ListView的适配器模式
- Android中优化ListView的ViewHolder模式
- 【Android】ListView多选模式的使用
- 【Android UI】ListView使用ViewHolder模式提高效率
- Android源码之ListView的适配器模式
- android ListView 去除下划线和选中模式
- Android listview多选模式ChoiceMode
- Android设计模式源码解析之ListView观察者模式
- Android设计模式源码解析之ListView观察者模式
- android- 开源 可拖拽listview ,支持多种模式操作
- android 多线程断点下载,listview 模式 开始 暂停等功能
- 《老罗Android》学习之UI ListView、MVC模式
- android基础笔记——使用viewholder模式优化ListView
- JQuery常用操作
- 53. Maximum Subarray LeetCode
- TensorFlow之卷积
- C#开发命名规范
- 光电编码器简介
- Android ListView长按多选模式
- HBase写性能优化策略
- Ubuntu 安装 Maven
- JavaScript_BOM
- 3.7
- 牛客网系列---Python
- 对java中FileInputStream、BufferInputStream的理解
- 常用框架、库
- Update layout parameters of view