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

更多相关文章

  1. Android(安卓)设置EditText的DrawableRight和DrawableLeft 的通
  2. Android添加权限AndroidManifes.xml
  3. android webview 显示不出来
  4. android webview的 一些设置(js java交互)
  5. Android动画Animator开发问题
  6. Android(安卓)ListView的item button点击无响应的解决方法
  7. Android开发——SQLite数据库(二)android studio创建数据库,进行插
  8. MPAndroidChart常见设置属性(一)——应用层
  9. Android(安卓)notification的使用实例

随机推荐

  1. Android禁止横竖屏和解决切换屏幕时重启A
  2. ubuntu 下进入android的终端 adb shell
  3. android top 10 library1
  4. Units of Measurement Supported by Andr
  5. Android如何使用WebView访问https的网站
  6. android开发小知识2
  7. Android(安卓)SDK Command line tools运
  8. Android中的Looper类
  9. Android的webView和h5+js交互
  10. Android对弹出输入法界面影响app界面布局