android 应用开发中经常遇到要将文件图片等数据列表按日期分类排序的需求,这里提供一个demo。10行代码就可以实现数据的分类和排序。
主要实现功能:
1.列表数据按日期分类,同一天数据归类到一个item中
2.列表数据按日期倒序排列
3.RecycleView嵌套RecycleView
4.支持多选,全选、取消全选
效果如下图:
这里提供Adapter的样例代码,其他的简单就不赘述了。
package com.justlink.nas.ui.main.home;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Handler;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.DataSource;
import com.bumptech.glide.load.engine.GlideException;
import com.bumptech.glide.request.RequestListener;
import com.bumptech.glide.request.target.Target;
import com.bumptech.glide.signature.ObjectKey;
import com.justlink.nas.R;
import com.justlink.nas.application.MyApplication;
import com.justlink.nas.bean.FileBean;
import com.justlink.nas.constans.MyConstants;
import com.justlink.nas.ui.main.file.ImageDisplayActivity;
import com.justlink.nas.utils.DateUtils;
import com.justlink.nas.utils.LogUtil;
import com.justlink.nas.utils.StringUtil;
import com.justlink.nas.widget.RoundImageView;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class FileTypeListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private Context mContext;
private ArrayList<FileBean> fileList; //数据源
private ArrayList<FileBean> selectList; //已选中的数据
private ArrayList<FileBean> hasSortedList; //已排序后的数据
private boolean[] mCheckedFlags; //选中标识
private OnItemClickListener mListener;
private boolean showCheckbox = true; //是否显示选中图标
private int fileType = 1; //文件类型1:视频 2:音乐 3:图片 4:文档
private HashMap<String,ArrayList<FileBean>> mulitDatas; //数据分类map
private List<Map.Entry<String, ArrayList<FileBean>>> sortedList; //分类排序数据
public FileTypeListAdapter(Context context, ArrayList<FileBean> datas,int mtype) {
this.mContext = context;
this.fileList = datas;
this.fileType = mtype;
mCheckedFlags = new boolean[fileList.size()];
selectList = new ArrayList<>();
hasSortedList = new ArrayList<>();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
sortDatas();
}
}
@RequiresApi(api = Build.VERSION_CODES.N)
private void sortDatas() {
if(fileType==1 || fileType==3){
mulitDatas = new HashMap<>();
// 将数据按日期分类,存储在HashMap<String,ArrayList<Bean>>中
fileList.stream().forEach(bean -> {
String date = bean.getTime(); // 获取日期
ArrayList<FileBean> beanList = mulitDatas.getOrDefault(date, new ArrayList<>());
beanList.add(bean);
mulitDatas.put(date, beanList);
// LogUtil.showLog("image","===sortedList doing=="+bean.getName());
});
// 将分类好的数据按倒序排列
sortedList = new ArrayList<>(mulitDatas.entrySet());
Collections.sort(sortedList, (entry1, entry2) -> entry2.getKey().compareTo(entry1.getKey()));
LogUtil.showLog("image","===sortedList size=="+sortedList.size());
hasSortedList.clear();
for (int i = 0; i < sortedList.size(); i++) {
hasSortedList.addAll(sortedList.get(i).getValue());
}
}
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
if (fileType == 1 || fileType == 3) {
showCheckbox = false;
return new ImageVideoHolder(LayoutInflater.from(mContext).inflate(R.layout.item_file_type_image_video, parent, false));
}else {
showCheckbox = true;
return new MyHolder(LayoutInflater.from(mContext).inflate(R.layout.item_file_list_select, parent, false));
}
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
if (fileType == 1 || fileType == 3) { //视频、图片
ImageVideoHolder imageVideoHolder = (ImageVideoHolder) holder;
imageVideoHolder.tvDate.setText(sortedList.get(position).getKey());
GridLayoutManager layoutManager = new GridLayoutManager(mContext,4);
imageVideoHolder.rvSubList.setLayoutManager(layoutManager);
imageVideoHolder.rvSubList.addItemDecoration(new GridSpacingItemDecoration(4,10,true));
imageVideoHolder.rvSubList.setAdapter(new SublistAdapter(sortedList.get(position).getValue(),position));
imageVideoHolder.tvSelect.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
showCheckbox = true;
notifyDataSetChanged();
}
});
} else { //音乐、文档
MyHolder myHolder = (MyHolder) holder;
myHolder.fileName.setText(fileList.get(position).getName());
myHolder.ivIcon.setImageResource(fileList.get(position).getType() != 0 ? R.mipmap.icon_dir : R.mipmap.icon_file_other);
myHolder.fileTime.setText(fileList.get(position).getModifyTime());
myHolder.cbSelect.setVisibility(showCheckbox ? View.VISIBLE : View.GONE);
myHolder.cbSelect.setChecked(mCheckedFlags[myHolder.getAdapterPosition()]);
myHolder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mListener.onItemClick(myHolder.getAdapterPosition());
}
});
myHolder.cbSelect.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
mCheckedFlags[myHolder.getAdapterPosition()] = b;
mListener.onFileSelect(getSelectCount());
}
});
}
}
@Override
public int getItemCount() {
if(fileType==2 || fileType==4) {
return fileList.size();
}else {
if(sortedList.size()==0)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
sortDatas();
LogUtil.showLog("image","===sortedList again size=="+sortedList.size());
}
return sortedList.size();
}
}
class MyHolder extends RecyclerView.ViewHolder {
private TextView fileName, filePath, fileTime;
private CheckBox cbSelect;
private ImageView ivIcon;
public MyHolder(@NonNull View itemView) {
super(itemView);
fileName = itemView.findViewById(R.id.tv_file_name);
filePath = itemView.findViewById(R.id.tv_file_sub);
fileTime = itemView.findViewById(R.id.tv_file_time);
cbSelect = itemView.findViewById(R.id.cb_select);
ivIcon = itemView.findViewById(R.id.iv_icon);
}
}
class ImageVideoHolder extends RecyclerView.ViewHolder {
private TextView tvDate, tvSelect;
private RecyclerView rvSubList;
public ImageVideoHolder(@NonNull View itemView) {
super(itemView);
tvDate = itemView.findViewById(R.id.tv_file_data);
tvSelect = itemView.findViewById(R.id.tv_file_select);
rvSubList = itemView.findViewById(R.id.rv_item_list);
}
}
public void refrsh(ArrayList<FileBean> list) {
fileList.clear();
fileList.addAll(list);
mCheckedFlags = new boolean[fileList.size()];
notifyDataSetChanged();
}
public void selectAll(boolean flag) {
showCheckbox = flag;
for (int i = 0; i < mCheckedFlags.length; i++) {
mCheckedFlags[i] = flag;
}
notifyDataSetChanged();
mListener.onFileSelect(getSelectCount());
}
public interface OnItemClickListener {
void onItemClick(int position);
void onFileSelect(int count);
}
public void setOnItemClickListener(OnItemClickListener listener) {
this.mListener = listener;
}
private int getSelectCount() {
int count = 0;
for (boolean flag : mCheckedFlags) {
if (flag)
count++;
}
return count;
}
public ArrayList<FileBean> getSelectList() {
selectList.clear();
for (int i = 0; i < mCheckedFlags.length; i++) {
if (mCheckedFlags[i]) {
selectList.add(fileList.get(i));
LogUtil.showLog("file", "==select file==" + fileList.get(i).getName());
}
}
return selectList;
}
public void setShowCheckbox(boolean showCheckbox) {
this.showCheckbox = showCheckbox;
}
public void setFileType(int fileType) {
this.fileType = fileType;
}
class SublistAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{
private ArrayList<FileBean> sublist;
private int parentIndex; //子列表所在父列表的位置
public SublistAdapter(ArrayList<FileBean> list,int index){
this.sublist = list;
this.parentIndex = index;
LogUtil.showLog("image","===sublist data size=="+sublist.size());
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return new SubListHolder(LayoutInflater.from(mContext).inflate(R.layout.item_sublist_image_video,parent,false));
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
SubListHolder subListHolder = (SubListHolder) holder;
subListHolder.iconVideo.setVisibility(fileType==1?View.VISIBLE:View.GONE);
subListHolder.cbSelect.setVisibility(showCheckbox?View.VISIBLE:View.GONE);
String path = "";
if(TextUtils.isEmpty(sublist.get(position).getDir()))
path = sublist.get(position).getName();
else
path = sublist.get(position).getDir()+"/"+sublist.get(position).getName();
String url = MyConstants.file_http_base_url+path+"?disk="+ MyApplication.storeList.get(MyApplication.currentStoreId).getPosition()+"&user="+MyApplication.userLoginID+"&device_id="+MyApplication.currentDevID+"&filetype=data&scale="+(fileType==1?"video":"thumb");
LogUtil.showLog("image","===url=="+url);
Glide.with(mContext).load(url).listener(new RequestListener<Drawable>() {
@Override
public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
//图片加载失败时回调
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
Glide.with(mContext).load(url).placeholder(R.mipmap.icon_album).into(subListHolder.ivImage);
}
},3000);
return false;
}
@Override
public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
//图片加载成功时回调
return false;
}
}).signature(new ObjectKey(url)).placeholder(R.mipmap.icon_album).into(subListHolder.ivImage);
subListHolder.cbSelect.setChecked(mCheckedFlags[getFileIndexInTotalList(subListHolder.getAdapterPosition())]);
subListHolder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mListener.onItemClick(getFileIndexInTotalList(subListHolder.getAdapterPosition()));
}
});
subListHolder.cbSelect.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
mCheckedFlags[getFileIndexInTotalList(subListHolder.getAdapterPosition())] = b;
mListener.onFileSelect(getSelectCount());
}
});
}
@Override
public int getItemCount() {
return sublist.size();
}
class SubListHolder extends RecyclerView.ViewHolder {
private RoundImageView ivImage;
private ImageView iconVideo;
private CheckBox cbSelect;
public SubListHolder(@NonNull View itemView) {
super(itemView);
ivImage = itemView.findViewById(R.id.riv_img);
iconVideo = itemView.findViewById(R.id.icon_video);
cbSelect = itemView.findViewById(R.id.cb_select);
}
}
//获取当前子列表item在总列表中的位置索引
public int getFileIndexInTotalList(int subIndex){
int totalIndex = 0;
for (int i = 0; i < parentIndex; i++) {
totalIndex += sortedList.get(i).getValue().size();
}
totalIndex += subIndex;
return totalIndex;
}
}
//获取排序后的总数据集合
public ArrayList<FileBean> getSortedTotalList(){
return hasSortedList;
}
}