Android(安卓)RecyclerView设置多选
Android RecyclerView设置多选
本篇文章记录如何使用recyclerView,通过适配器来实现recyclerView的多选。点击多选按钮时每个item后面会显示一个checkBox,取消时checkBox会隐藏。要点如下:
- recyclerView+Adapter
- 自定义view的dialog
- 自定义的popupWindow
一、实现基本的recyclerView+Adapter
/** * Created by stephen on 17-8-12. * 文件列表recyclerView适配器 */public class RecordingsAdapter extends RecyclerView.Adapter { private List recordingFileList; private static List multipleFileList=new ArrayList<>();//多选选择的文件集合 private SavedRecordingsFragment s; private boolean ifRenameClicked=false; private boolean ifDeleteClicked=false; private boolean ifMultipleDeleteClicked=false; private PopupWindowRename popupWindowRename;//重命名popupWindow private PopupWindowDelete popupWindowDelete;//确认删除popupWindow private MultipleDeletePopup multipleBottomDialog;//多选删除popupWindow private static final String PLAY_DIALOG="com.example.stephen.soundrecorder.action.PLAY_DIALOG"; private static final String NOTIFY_RECYCLER_VIEW="com.example.stephen.soundrecorder.action.NOTIFY_RECYCLER_VIEW"; //录音文件存储父路径 final private File fileDir=new File(Environment.getExternalStorageDirectory(),"/RecordFile"); private Dialog bottomDialog;//底部选择dialog(delete,rename,share,multiple) private boolean ifMultiple=false;//是否多选 static class ViewHolder extends RecyclerView.ViewHolder{ TextView fileName,fileLength,fileData; CheckBox checkBox; View view; public ViewHolder(View itemView) { super(itemView); view=itemView; fileName=(TextView) itemView.findViewById(R.id.name_recording_file); fileLength=(TextView)itemView.findViewById(R.id.length_recording_file); fileData=(TextView)itemView.findViewById(R.id.data_recording_file); checkBox=(CheckBox)itemView.findViewById(R.id.check_recording_file); } } public RecordingsAdapter(List list, SavedRecordingsFragment s) { this.recordingFileList =list; this.s=s; } /** * 按键响应,点击item播放录音 * 长按item滑出底部dialog,选择删除/重命名操作 * @param parent * @param viewType */ @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { final View view= LayoutInflater.from(parent.getContext()).inflate(R.layout.recycler_item_recordings,parent,false); final ViewHolder viewHolder=new ViewHolder(view); viewHolder.view.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //若在多选删除情况下,点击item选择/取消checkbox,不能播放 if (ifMultiple){ if (viewHolder.checkBox.isChecked()){ viewHolder.checkBox.setChecked(false); }else viewHolder.checkBox.setChecked(true); return; } int position = viewHolder.getAdapterPosition(); RecordingFiles recordingFiles = recordingFileList.get(position); Gson gson=new Gson(); String recordJsonStr= gson.toJson(recordingFiles); Intent intent = new Intent(PLAY_DIALOG); intent.putExtra("record_json",recordJsonStr); v.getContext().sendBroadcast(intent); } }); viewHolder.view.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { if (!ifMultiple){ longClickListener(viewHolder); } return true; } }); viewHolder.checkBox.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { int selectedPosition = viewHolder.getAdapterPosition(); RecordingFiles selectedRecordingFiles = recordingFileList.get(selectedPosition); if (viewHolder.checkBox.isChecked()){ //若被选中 multipleFileList.add(selectedRecordingFiles); }else { multipleFileList.remove(selectedRecordingFiles); } } }); return viewHolder; } @Override public void onBindViewHolder(ViewHolder holder, int position) { RecordingFiles recordingFiles=recordingFileList.get(position); holder.fileData.setText(recordingFiles.getFileData()); holder.fileName.setText(recordingFiles.getFileName()); holder.fileLength.setText(CalculateDurationToTime.calTime(recordingFiles.getFileLength())); if (ifMultiple){ holder.checkBox.setVisibility(View.VISIBLE); holder.checkBox.setChecked(false); }else { holder.checkBox.setVisibility(View.INVISIBLE); } } @Override public int getItemCount() { return recordingFileList.size(); } private View.OnClickListener itemsOnClick =new View.OnClickListener() { @Override public void onClick(View v) { switch (v.getId()) { case R.id.popup_rename_ok: ifRenameClicked=true; popupWindowRename.dismiss(); break; case R.id.popup_rename_cancel: ifRenameClicked=false; popupWindowRename.dismiss(); break; case R.id.popup_delete_ok: ifDeleteClicked=true; popupWindowDelete.dismiss(); break; case R.id.popup_delete_cancel: ifDeleteClicked=false; popupWindowDelete.dismiss(); break; case R.id.cancel_multiple_recording_file: multipleBottomDialog.dismiss(); break; case R.id.delete_multiple_recording_file: ifMultipleDeleteClicked=true; multipleBottomDialog.dismiss(); default: break; } } }; //长按item弹出底部popuWindow private void longClickListener(ViewHolder viewHolder){ int position = viewHolder.getAdapterPosition(); final RecordingFiles recordingFiles = recordingFileList.get(position);//选中的文件 bottomDialog=new Dialog(s.getContext(),R.style.BottomDialog); LinearLayout root=(LinearLayout)LayoutInflater.from(s.getContext()).inflate(R.layout.bottom_dialog,null); //初始化底部dialog视图,设置按键响应 //分享按键 root.findViewById(R.id.multiple_recording_file).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { multipleDeleteFile(); } }); //分享按键 root.findViewById(R.id.share_recording_file).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { shareFile(new File(fileDir,recordingFiles.getFileName())); } }); //删除按键 root.findViewById(R.id.delete_recording_file).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { deleteFile(new File(fileDir,recordingFiles.getFileName())); } }); //重命名按键 root.findViewById(R.id.rename_recording_file).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { renameFile(new File(fileDir,recordingFiles.getFileName())); } }); bottomDialog.setContentView(root); Window dialogWindow = bottomDialog.getWindow(); dialogWindow.setGravity(Gravity.BOTTOM); WindowManager.LayoutParams lp = dialogWindow.getAttributes(); // 获取对话框当前的参数值 lp.x = 0; // 新位置X坐标 lp.y = 0; // 新位置Y坐标 lp.width = (int) s.getContext().getResources().getDisplayMetrics().widthPixels; // 宽度 root.measure(0, 0); lp.height = root.getMeasuredHeight(); lp.alpha = 9f; // 透明度 dialogWindow.setAttributes(lp); bottomDialog.show(); } //删除多选的文件 public void multipleDeleteFile(){ bottomDialog.dismiss();//隐藏底部dialog ifMultiple=true;//设置多选框可见 //发送广播更新recycler view Intent intent=new Intent(NOTIFY_RECYCLER_VIEW); s.getContext().sendBroadcast(intent); //弹出底部删除/取消选择框 multipleBottomDialog=new MultipleDeletePopup(s.getContext(),itemsOnClick); multipleBottomDialog.showAtLocation(s.getView(),Gravity.BOTTOM,0,0); multipleBottomDialog.setOnDismissListener(new PopupWindow.OnDismissListener() { @Override public void onDismiss() { if (ifMultipleDeleteClicked){ for (RecordingFiles recordings:multipleFileList){ File tempFile= new File(fileDir,recordings.getFileName()); if (tempFile.exists())tempFile.delete(); } ifMultipleDeleteClicked=false; } //清空multipleFileList multipleFileList.clear(); ifMultiple=false; //发送广播更新recycler view Intent intent=new Intent(NOTIFY_RECYCLER_VIEW); s.getContext().sendBroadcast(intent); } }); } //分享文件 private void shareFile(File file){ bottomDialog.dismiss();//隐藏底部dialog setWindowAlpha(0.6f);//设置背景模糊,需要使用getActivity().getWindow(),所以需要在adapter构造器中传入fragment实例 Intent shareIntent = new Intent(); shareIntent.setAction(Intent.ACTION_SEND); shareIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(file)); shareIntent.setType("audio/mp4"); s.getContext().startActivity(Intent.createChooser(shareIntent,"发送至")); setWindowAlpha(1f); } //删除文件 private void deleteFile(final File file){ bottomDialog.dismiss();//隐藏底部dialog popupWindowDelete=new PopupWindowDelete(s.getContext(),itemsOnClick,file.getName()); popupWindowDelete.showAtLocation(s.getView(),Gravity.CENTER,0,0); //设置背景模糊,需要使用getActivity().getWindow(),所以需要在adapter构造器中传入fragment实例 setWindowAlpha(0.6f); //bottomPopupWindow消失后恢复fragment透明度 //并判断是否点击了确定按钮 //若点击了,就执行删除文件操作 popupWindowDelete.setOnDismissListener(new PopupWindow.OnDismissListener() { @Override public void onDismiss() { setWindowAlpha(1f); if (ifDeleteClicked){ if (file.exists()){ file.delete(); Toast.makeText(s.getContext(),file.getName()+"文件已删除!",Toast.LENGTH_SHORT).show(); //发送广播更新recycler view Intent intent=new Intent(NOTIFY_RECYCLER_VIEW); s.getContext().sendBroadcast(intent); } ifDeleteClicked=false; } } }); } //重命名文件 private void renameFile(final File file){ bottomDialog.dismiss(); popupWindowRename =new PopupWindowRename(s.getContext(),itemsOnClick,file.getName().substring(0,file.getName().length()-4)); popupWindowRename.showAtLocation(s.getView(),Gravity.CENTER,0,0); //设置背景模糊,需要使用getActivity().getWindow(),所以需要在adapter构造器中传入fragment实例 setWindowAlpha(0.6f); //bottomPopupWindow消失后恢复fragment透明度 //并判断是否点击了确定按钮 //若点击了,就执行重命名操作 popupWindowRename.setOnDismissListener(new PopupWindow.OnDismissListener() { @Override public void onDismiss() { setWindowAlpha(1f); if (ifRenameClicked){ Log.d("RecorderAdapter",file.getAbsolutePath()); if (file.exists()){ Log.d("RecorderAdapter","file exist!!!"); File renameFile=new File(fileDir, popupWindowRename.getEditText()+".mp3"); file.renameTo(renameFile); //发送广播更新recycler view Intent intent=new Intent(NOTIFY_RECYCLER_VIEW); s.getContext().sendBroadcast(intent); } ifRenameClicked=false; } } }); } //设置fragment透明度 private void setWindowAlpha(float f){ WindowManager.LayoutParams lp=s.getActivity().getWindow().getAttributes(); lp.alpha = f; //0.0-1.0 s.getActivity().getWindow().setAttributes(lp); }}
-以上是adapter的全部代码,先贴出来
二、下面详细讲解一下实现过程
首先,长按item时,会跳出一个底部dialog。既代码中的bottomDialog,这里有四个选项,分别为:多选、分享、删除和重命名。后面三个我们不去管,只看第一个多选。
点击多选按钮时,底部的bottomDialog会dimiss,这时提醒adapter刷新,所有item的checkBox会被设置称VISIBLE,且都是uncheck。具体实现在multipleDeleteFile()函数。
我们来仔细看一下这个函数:
1.首先给变量ifMultiple赋值为true,再更新adapter
这里设置ifMultiple为true后再去加载adapter时,我们看到在onBindViewHolder()函数里,会设置checkBox为VISIBLE,同时初始化为uncheck;
public void onBindViewHolder(ViewHolder holder, int position) { RecordingFiles recordingFiles=recordingFileList.get(position); holder.fileData.setText(recordingFiles.getFileData()); holder.fileName.setText(recordingFiles.getFileName()); holder.fileLength.setText(CalculateDurationToTime.calTime(recordingFiles.getFileLength())); if (ifMultiple){ holder.checkBox.setVisibility(View.VISIBLE); holder.checkBox.setChecked(false); }else { holder.checkBox.setVisibility(View.INVISIBLE); } }
然后在onCreateViewHolder()函数中,设置item的点击响应事件,之前是点击就会播放这段录音,现在当ifMultiple为true时,点击item就会改变checkBox的选择状态并返回,也就是不会再播放录音来,同时长按item也不会有响应。
@Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { final View view= LayoutInflater.from(parent.getContext()).inflate(R.layout.recycler_item_recordings,parent,false); final ViewHolder viewHolder=new ViewHolder(view); viewHolder.view.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //若在多选删除情况下,点击item选择/取消checkbox,不能播放 if (ifMultiple){ if (viewHolder.checkBox.isChecked()){ viewHolder.checkBox.setChecked(false); }else viewHolder.checkBox.setChecked(true); return; } int position = viewHolder.getAdapterPosition(); RecordingFiles recordingFiles = recordingFileList.get(position); Gson gson=new Gson(); String recordJsonStr= gson.toJson(recordingFiles); Intent intent = new Intent(PLAY_DIALOG); intent.putExtra("record_json",recordJsonStr); v.getContext().sendBroadcast(intent); } }); viewHolder.view.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { //若在多选删除情况下,长按item没有响应 if (!ifMultiple){ longClickListener(viewHolder); } return true; } }); viewHolder.checkBox.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { int selectedPosition = viewHolder.getAdapterPosition(); RecordingFiles selectedRecordingFiles = recordingFileList.get(selectedPosition); if (viewHolder.checkBox.isChecked()){ //若被选中 multipleFileList.add(selectedRecordingFiles); }else { multipleFileList.remove(selectedRecordingFiles); } } }); return viewHolder; }
2.我们接着看multipleDeleteFile函数,接下来弹出一个底部的自定义popupWindowFragment,类似于dialog,里面有两个按钮:删除和取消。当用户选择了一定数量的item后点击删除时,执行如下代码:
if (ifMultipleDeleteClicked){ for (RecordingFiles recordings:multipleFileList){ File tempFile= new File(fileDir,recordings.getFileName()); if (tempFile.exists())tempFile.delete(); } ifMultipleDeleteClicked=false;}
multipleFileList是一个全局变量,他会记录所有被选中的录音文件,然后在这里遍历这个list删除选中的文件。
3.最后在执行如下代码,清空list并发送广播更新recyclerView
multipleFileList.clear(); ifMultiple=false; //发送广播更新recycler view Intent intent=new Intent(NOTIFY_RECYCLER_VIEW); s.getContext().sendBroadcast(intent);
更多相关文章
- Android(安卓)设置EditText的DrawableRight和DrawableLeft 的通
- Android添加权限AndroidManifes.xml
- android webview 显示不出来
- android webview的 一些设置(js java交互)
- Android动画Animator开发问题
- Android(安卓)ListView的item button点击无响应的解决方法
- Android开发——SQLite数据库(二)android studio创建数据库,进行插
- MPAndroidChart常见设置属性(一)——应用层
- Android(安卓)notification的使用实例