1.项目效果图
2.实现技术
(1)长按点击的操作与外部SwipeRecyclerView结合进行使用,这一块具体的操作可以看之前的博客里面有介绍。
(2)其次就是view的显示,当进行长按或者点击编辑时显示checkbox,当正常情况时不显示checkbox
(3)用什么数据结构存储选中状态。Map数据结构Map<Integer,boolean>:
key值为item所在的position,value值为checkbox状态,选中为true,未选中为false
(4)获取选中数据的个数:遍历map集合,统计value值为true
(5)取消:直接将map中的value值全为false
(6)全选:直接将map中的value值全为true
(7)反选:将map中value的值设为当前value值取反后的值
3.代码实现
Activity实现:
这里的代码主要是实现编辑和长按的操作,对于数据的获取没有进行代码展示,这块可以直接看recyclerview的博客:http://t.csdn.cn/ry0Pp
package com.dcampus.weblib.resource;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.ItemTouchHelper;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import android.Manifest;
import android.app.AlertDialog;
import android.content.ComponentName;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Parcelable;
import android.util.Log;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.PopupMenu;
import android.widget.TextView;
import android.widget.Toast;
import com.yanzhenjie.recyclerview.OnItemClickListener;
import com.yanzhenjie.recyclerview.OnItemLongClickListener;
import com.yanzhenjie.recyclerview.OnItemMenuClickListener;
import com.yanzhenjie.recyclerview.SwipeMenu;
import com.yanzhenjie.recyclerview.SwipeMenuBridge;
import com.yanzhenjie.recyclerview.SwipeMenuCreator;
import com.yanzhenjie.recyclerview.SwipeMenuItem;
import com.yanzhenjie.recyclerview.SwipeRecyclerView;
import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.core.Observer;
import io.reactivex.rxjava3.disposables.Disposable;
import io.reactivex.rxjava3.schedulers.Schedulers;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import static com.dcampus.weblib.set.SetFragment.mIsWifiMode;
public class MyResourceActivity extends AppCompatActivity{
//编辑模式
private final static int CHECK_MODE=0;
private final static int EDIT_MODE=1;
private int mEditMode=CHECK_MODE; //初始为未编辑
private boolean editable = false; //当前界面是否可编辑
private Map<Integer,Boolean> map_check=new HashMap<>(); //利用map存储checkbox的状态
private TextView bt_select_all;
private int checkedNumber=0; //选中数量
private TextView edit_mode_title;
private TextView bt_edit;
FrameLayout frameLayout_edit;
Toolbar toolbar_no_edit;
private SwipeRecyclerView recyclerView;
private List<DirResponse.OnlineFile> fileList = new ArrayList<>();
private List<DirResponse.OnlineFile> files=new ArrayList<>();
private ResourceAdapter resourceAdapter;
private TextView bt_edit_cancel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my_resource);
bt_select_all=findViewById(R.id.button_select_all);
//全选
bt_select_all.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
getSelectAll();
}
});
edit_mode_title=findViewById(R.id.edit_mode_title);
frameLayout_edit=findViewById(R.id.toolbar_edit);
toolbar_no_edit=findViewById(R.id.toolbar_rm);
//编辑模式中取消按钮
bt_edit_cancel=findViewById(R.id.button_edit_cancel);
bt_edit_cancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
hideEdit();
//将目前checkbox全部为false
// Set<Map.Entry<Integer,Boolean>> set=map_check.entrySet();
// for(Map.Entry<Integer,Boolean> entry:set){
// entry.setValue(false);
// }
}
});
swipeRefreshLayout =findViewById(R.id.ll_refresh);
bt_edit=findViewById(R.id.bt_title);
recyclerView =findViewById(R.id.rv_resourcemanage);
//设置分割线
DividerItemDecoration decoration = new DividerItemDecoration(this, DividerItemDecoration.VERTICAL);
recyclerView.addItemDecoration(decoration);
initR();
//加载控件
initView();
getResourceData3();
//点击编辑
bt_edit.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
updateEditMode();
}
});
//得到资源列表
private void getResourceData3(){
//这一部分可以写自己加载recyclerView数据
}
//全选方法
private void getSelectAll() {
resourceAdapter.selectAll();
checkedNumber=resourceAdapter.getCheckedNumber();
if(checkedNumber!=0){
edit_mode_title.setText("已选择"+checkedNumber+"项");
}else{
edit_mode_title.setText("请选择文件");
}
}
//隐藏编辑模式
private void hideEdit(){
mEditMode=EDIT_MODE;
updateEditMode();
resourceAdapter.cancel(); //将map中的值均变成false
getCheckNumber();
}
private void getCheckNumber(){
checkedNumber=resourceAdapter.getCheckedNumber();
System.out.println("checknumber1"+checkedNumber);
if(checkedNumber!=0){
edit_mode_title.setText("已选择"+checkedNumber+"项");
}else{
edit_mode_title.setText("请选择文件");
}
}
//更新编辑模式
private void updateEditMode() {
mEditMode= mEditMode==CHECK_MODE ? EDIT_MODE :CHECK_MODE;
if(mEditMode==EDIT_MODE){
//当前页面可以编辑
frameLayout_edit.setVisibility(View.VISIBLE);
toolbar_no_edit.setVisibility(View.GONE);
bottomBar.setVisibility(View.GONE);
bottomBar_edit.setVisibility(View.VISIBLE);
editable=true;
}
else{
//当前页面不可编辑
toolbar_no_edit.setVisibility(View.VISIBLE);
bottomBar.setVisibility(View.VISIBLE);
bottomBar_edit.setVisibility(View.GONE);
editable=false;
}
resourceAdapter.setEditMode(mEditMode);
}
private void initR(){
//可以直接调用swipeRecyclerView框架里面的点击子项、点击长按事件
recyclerView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(View view, int position) {
//不可编辑模式下点开文件夹或下载
if(editable==false){
//不可编辑模式下自己做的操作
}
if(editable==true){
//可编辑模式下
map_check.put(position,!map_check.get(position));
resourceAdapter.notifyDataSetChanged();
//获得选中数量
checkedNumber=resourceAdapter.getCheckedNumber();
System.out.println("check1"+checkedNumber);
if(checkedNumber!=0){
edit_mode_title.setText("已选择"+checkedNumber+"项");
//得到选择id数组
chooseId=new int[checkedNumber];
chooseId=resourceAdapter.getChooseID();
choosePosition=resourceAdapter.getChoosePosition();
for (int i = 0; i < chooseId.length; i++) {
Log.d("choose数量", String.valueOf(chooseId.length));
Log.d("choose", String.valueOf(chooseId[i]));
}
}else{
edit_mode_title.setText("请选择文件");
}
}
}
});
//长按
recyclerView.setOnItemLongClickListener(new OnItemLongClickListener() {
@Override
public void onItemLongClick(View view, int position) {
if(mEditMode==CHECK_MODE){
//进入编辑
updateEditMode();
// map_check.put(position,true);
resourceAdapter.selectOne(position);
checkedNumber=resourceAdapter.getCheckedNumber();
if(checkedNumber!=0){
edit_mode_title.setText("已选择"+checkedNumber+"项");
}else{
edit_mode_title.setText("请选择文件");
}
}else{
hideEdit();
}
});
}
//recyclerview
private void initView() {
//找到控件
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(MyResourceActivity.this, LinearLayoutManager.VERTICAL, false);
recyclerView.setLayoutManager(linearLayoutManager);
resourceAdapter = new ResourceAdapter(fileList, MyResourceActivity.this,map_check);
recyclerView.setAdapter(resourceAdapter);
}
}
}
Adapter实现:
同样主要是实现编辑的操作,在数据加载部分没有做多余的展示。
package com.dcampus.weblib.resource;
import android.content.Context;
import android.graphics.Color;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
import org.apache.commons.lang3.StringUtils;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.dcampus.weblib.R;
import com.dcampus.weblib.WebLibApplication;
import com.dcampus.weblib.api.ResourceApiService;
import com.dcampus.weblib.bean.entityRoom.DBResourceThumbnail;
import com.dcampus.weblib.bean.response.resource.GetResourcesResponse;
import com.dcampus.weblib.bean.response.resource.GetThumbnailResponse;
import com.dcampus.weblib.data.constant.FileType;
import com.dcampus.weblib.data.repository.ResourceThumbnailRepository;
import com.dcampus.weblib.data.resource.NewNode;
import com.dcampus.weblib.data.resource.Resource;
import com.dcampus.weblib.data.resource.download.DownloadInfo;
import com.dcampus.weblib.network.RetrofitUtils;
import com.dcampus.weblib.utils.FileUtil;
import com.dcampus.weblib.utils.StringUtil;
import com.facebook.drawee.view.SimpleDraweeView;
import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.core.SingleObserver;
import io.reactivex.rxjava3.disposables.Disposable;
import io.reactivex.rxjava3.schedulers.Schedulers;
import retrofit2.http.Url;
public class ResourceAdapter extends RecyclerView.Adapter<ResourceAdapter.MyViewHolder> {
private final static int CHECK_MODE=0;
private int mEditMode=CHECK_MODE;
private List<DirResponse.OnlineFile> fileList=new ArrayList<>();
private List<Integer> resourceWithThumbnail=new ArrayList<>();
private Context context;
private Map<Integer,Boolean> map_check=new HashMap<>(); //利用map存储checkbox的状态
private int number;
public ResourceAdapter(List<DirResponse.OnlineFile> fileList, Context context, Map<Integer, Boolean> map_check) {
this.fileList = fileList;
this.context = context;
this.map_check = map_check;
}
public ResourceAdapter(List<DirResponse.OnlineFile> fileList, Context context) {
this.fileList = fileList;
this.context = context;
}
//找到view
@NonNull
@NotNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull @NotNull ViewGroup parent, int viewType) {
View view= LayoutInflater.from(context).inflate(R.layout.list_item_resource_manage,null);
return new MyViewHolder(view);
}
//给每个item赋值
@Override
public void onBindViewHolder(@NonNull @NotNull ResourceAdapter.MyViewHolder holder, int position) {
//判断是否为可编辑状态
if(mEditMode==CHECK_MODE){
holder.checkBox.setVisibility(View.GONE);
}else{
holder.checkBox.setVisibility(View.VISIBLE);
holder.checkBox.setChecked(map_check.get(position));
}
}
//返回item的数量
@Override
public int getItemCount() {
return fileList.size();
}
public class MyViewHolder extends RecyclerView.ViewHolder {
private SimpleDraweeView type;//文件类型
private TextView name;//文件名
private TextView tvDesc; //资源大小(文件)
private ImageView iv_next;//下一步
private CheckBox checkBox;
private TextView tvFolder; //资源名(文件夹、柜子、分类)
private TextView tvFolderProcess; //资源下载进度(文件夹)
private LinearLayout llDetail; //文件资源名与资源大小显示的外层 layout,用于隐藏和显示
private ProgressBar pbBackground; //item 下载进度背景
public MyViewHolder(@NonNull @NotNull View itemView) {
super(itemView);
type = itemView.findViewById(R.id.iv_node_img);
name = itemView.findViewById(R.id.weblib_item_name);
iv_next=itemView.findViewById(R.id.iv_arrow);
checkBox=itemView.findViewById(R.id.list_cb);
tvFolder = itemView.findViewById(R.id.tv_folder);
tvFolderProcess = itemView.findViewById(R.id.tv_folder_process);
llDetail = itemView.findViewById(R.id.ll_detail);
pbBackground = itemView.findViewById(R.id.pb_background);
tvDesc = itemView.findViewById(R.id.descTextView);
/*
itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(onItemClickListener!=null){
onItemClickListener.click(itemView,getAdapterPosition());
if(mEditMode!=CHECK_MODE){
// checkBox.setChecked(true);
map_check.put(getAdapterPosition(),!map_check.get(getAdapterPosition()));
// System.out.println(map_check);
notifyDataSetChanged();
}
}
}
});
*/
//点击事件
itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//更新map的boolean值
map_check.put(getAdapterPosition(),!map_check.get(getAdapterPosition()));
notifyDataSetChanged();
onItemClickListener.click(v,getAdapterPosition());
}
});
itemView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
if(onItemLongClickListener!=null){
onItemLongClickListener.longClick(itemView,getAdapterPosition());
}
return true;
}
});
}
}
//得到选择数量
public int getCheckedNumber(){
number=0;
if(mEditMode!=CHECK_MODE){
Set<Map.Entry<Integer,Boolean>> set=map_check.entrySet();
for(Map.Entry<Integer,Boolean>entry:set){
//entry.getvalue为true表示选中
if(entry.getValue()&& number< fileList.size()){
number=number+1;
}
}
}
System.out.println(number+"number");
return number;
}
//得到选择的position
public int[] getChoosePosition() {
List<Integer> choosePosition_list = new ArrayList<>();
if (mEditMode != CHECK_MODE) {
if (number != 0) {
choosePosition = new int[number];
//遍历map集合
Set<Map.Entry<Integer, Boolean>> set = map_check.entrySet();
for (Map.Entry<Integer, Boolean> entry : set) {
if (entry.getValue()) {
//先将id添加到list集合中
choosePosition_list.add(entry.getKey());
}
}
//将list集合转成数组形式
for (int i = 0; i < choosePosition_list.size(); i++) {
choosePosition[i] = choosePosition_list.get(i);
}
}
}
return choosePosition;
}
//取消方法
public void cancel(){
Set<Map.Entry<Integer,Boolean>> set=map_check.entrySet();
for(Map.Entry<Integer,Boolean> entry:set){
entry.setValue(false);
}
getCheckedNumber();
notifyDataSetChanged();
}
//全选
public void selectAll(){
boolean isChecked=false;
//遍历map
Set<Map.Entry<Integer,Boolean>> set=map_check.entrySet();
for(Map.Entry<Integer,Boolean> entry:set){
if(entry.getValue()==false){
isChecked=true;
break;
}
}
for(Map.Entry<Integer,Boolean> entry:set){
entry.setValue(isChecked);
}
getCheckedNumber();
notifyDataSetChanged();
}
//将长按的item选中
public void selectOne(int position){
map_check.put(position,true);
getCheckedNumber();
notifyDataSetChanged();
}
//更新编辑模式
public void setEditMode(int editMode) {
mEditMode = editMode;
notifyDataSetChanged();
}
}
View层:
activity中的view层可以直接由一个recyclerView展示,上面两个button按钮就行,由于项目的问题就不做这个的展示
主要可以看一下每个item的view,这里涉及到checkbox的展示:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:fresco="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="@dimen/item_height_48dp">
<RelativeLayout
android:id="@+id/rv_flag"
android:tag="slide_flag"
android:layout_width="match_parent"
android:background="@drawable/bg_white_item_clickable"
android:layout_height="@dimen/item_height_48dp">
<CheckBox
android:id="@+id/list_cb"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginStart="10dp"
android:layout_marginEnd="4dp"
android:visibility="gone"
android:button="@drawable/selector_cb_blue" />
<ProgressBar
android:id="@+id/pb_background"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="@dimen/item_height_48dp"
android:layout_alignParentTop="true"
android:layout_toEndOf="@+id/list_cb"
android:progressDrawable="@drawable/my_progressbar"
android:visibility="invisible" />
<com.facebook.drawee.view.SimpleDraweeView
android:id="@+id/iv_node_img"
android:layout_width="50dp"
android:layout_height="@dimen/item_height_48dp"
android:layout_toEndOf="@+id/list_cb"
android:contentDescription="@string/desc"
android:padding="6dp"
/>
<TextView
android:id="@+id/tv_folder"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginEnd="48dp"
android:layout_toEndOf="@+id/iv_node_img"
android:textColor="#000000"
android:textSize="@dimen/list_item_text_size_15sp"
android:maxLines="1"
android:ellipsize="end" />
<LinearLayout
android:id="@+id/ll_detail"
android:layout_width="wrap_content"
android:layout_height="@dimen/item_height_48dp"
android:layout_gravity="center_vertical"
android:orientation="vertical"
android:layout_toEndOf="@+id/tv_folder"
android:layout_marginEnd="48dp">
<TextView
android:id="@+id/weblib_item_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="2"
android:gravity="bottom"
android:textSize="@dimen/list_item_text_size_15sp"
android:maxLines="1"
android:ellipsize="end" />
<TextView
android:id="@+id/descTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="2"
android:textSize="13sp" />
</LinearLayout>
<TextView
android:id="@+id/tv_folder_process"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toLeftOf="@id/iv_arrow"
android:layout_centerVertical="true"
android:layout_marginRight="10dp"
android:textColor="@color/gray"
android:visibility="invisible" />
<ImageView
android:id="@+id/iv_arrow"
android:layout_width="wrap_content"
android:layout_height="24dp"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="10dp"
android:contentDescription="@string/desc"
android:src="@drawable/arrow" />
<ImageView
android:id="@+id/ic_drag_handle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:layout_marginEnd="10dp"
android:src="@drawable/ic_drag_handle_grey"
android:contentDescription="@null"
android:visibility="gone" />
<ImageView
android:id="@+id/button_watch"
android:layout_width="@dimen/item_height_48dp"
android:layout_height="@dimen/item_height_48dp"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:padding="4dp"
android:visibility="gone"
android:src="@drawable/ic_watch_selectable"
android:background="@drawable/bg_white_item_clickable"
android:scaleType="centerInside"
android:contentDescription="@null" />
</RelativeLayout>
</RelativeLayout>