引用方式
Gradle 7.0
以下,需要在项目级build.gradle
文件中加入
1 2 3 4 5 6
| allprojects { repositories { ... maven { url 'https://jitpack.io' } } }
|
Gradle 7.0
以上,需要在setting.gradle
文件中加入
1 2 3 4 5 6
| dependencyResolutionManagement { repositories { ... maven { url 'https://jitpack.io' } } }
|
远程仓库配置之后,即可在模块的build.gradle
中引入FileSelector
1 2 3
| dependencies { implementation 'com.github.xxinPro:FileSelector:1.0' }
|
启动方式
1、启动Activity
1 2 3 4 5 6 7 8 9 10 11 12
| FileSelector.create(this) .forResult(new OnResultCallbackListener() { @Override public void onResult(List<FileBean> result) { }
@Override public void onCancel() { } });
|
2、注入frameLayout
,其中forResult()
的第一个参数代表需要被注入的frameLayout
的id
1 2 3 4 5 6 7 8 9 10 11 12
| FileSelector.create(this) .forResult(R.id.frame_layout, new OnResultCallbackListener() { @Override public void onResult(List<FileBean> result) { }
@Override public void onCancel() { } });
|
操作文件
在选择文件后,FileSelector
将回调OnResultCallbackListener
的onResult()
方法,在onResult()
方法中通过List<FileBean>
集合可对文件进行操作
对于FileBean
类,其中仅包含一个可用的File
或DocumentFile
类型文件对象,因为在Android 11
及以上的系统中,data
或obb
目录中的子文件是DocumentFile
类型文件对象
可以通过如下方法判断FileBean
中包含的文件类型
方法名 | 返回结果 |
---|
public boolean isFileType() | 为true 时表示FileBean 中包含一个File 类型文件对象,反之为DocumentFile 类型文件对象 |
public boolean isDocumentFileType() | 为true 时表示FileBean 中包含一个DocumentFile 类型文件对象,反之为File 类型文件对象 |
通过如下方法可以获取FileBean
中包含的File
或DocumentFile
文件对象
方法名 | 返回结果 |
---|
public File getFile() | 获取FileBean 中包含的File 类型文件对象 |
public DocumentFile getDocumentFile() | 获取FileBean 中包含的DocumentFile 类型文件对象 |
通过如下方法可以对FileBean
类进行一些快捷操作
方法名 | 返回结果 |
---|
public long lastModified() | 取FileBean 中包含文件的最后修改时间 |
public long length() | 取FileBean 中包含文件的大小 |
public String getName() | 取FileBean 中包含文件的文件名 |
基本使用
设置起始路径
设置FileSelector
打开的起始路径,默认起始路径为/storage/emulated/0
,可以自定义设置为任何一个存在的路径,包括data(obb)
目录及其子目录,若data(obb)
目录或其子目录没有访问权限将会自动申请
1 2 3 4 5 6 7 8 9 10 11 12 13
| FileSelector.create(this) .setInitPath(Environment.getExternalStorageDirectory().getAbsolutePath()) .forResult(new OnResultCallbackListener() { @Override public void onResult(List<FileBean> result) { }
@Override public void onCancel() { } });
|
设置排序规则
设置文件列表的排序规则,默认根据文件名排序
1 2 3 4 5 6 7 8 9 10 11 12 13
| FileSelector.create(this) .setSortRule(SortRule.Name) .forResult(new OnResultCallbackListener() { @Override public void onResult(List<FileBean> result) { }
@Override public void onCancel() { } });
|
setSortRule()
重载方法的第二个参数用于控制是否逆序,为true
时代表逆序
1 2 3 4 5 6 7 8 9 10 11 12 13
| FileSelector.create(this) .setSortRule(SortRule.Name, true) .forResult(new OnResultCallbackListener() { @Override public void onResult(List<FileBean> result) { }
@Override public void onCancel() { } });
|
FileSelector
提供了如下三种排序规则
1 2 3 4 5
| public enum SortRule { Time, Name, Size, }
|
若不满足,可以使用自定义的排序规则;需要注意的是,设置自定义排序规则后FileSelector
中的排序规则将不生效
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| FileSelector.create(this) .selfSortRule(new Comparator<FileItemBean>() { @Override public int compare(FileItemBean o1, FileItemBean o2) { return 0; } }) .forResult(new OnResultCallbackListener() { @Override public void onResult(List<FileBean> result) { }
@Override public void onCancel() { } });
|
自定义文件图标
FileSelector
提供了默认的文件图标,若不满足可以对文件图标进行自定义设置
未知文件图标
FileSelector
通过文件的后缀名来设置对应的图标,所以当文件有一些不明所以的后缀名时,FileSelector
将会为其设置一个未知文件图标,通过如下代码可以对该图标进行自定义
1 2 3 4 5 6 7 8 9 10 11 12 13
| FileSelector.create(this) .setDefaultFileIcon(R.drawable.file_icon) .forResult(new OnResultCallbackListener() { @Override public void onResult(List<FileBean> result) { }
@Override public void onCancel() { } });
|
文件夹图标
自定义文件夹图标
1 2 3 4 5 6 7 8 9 10 11 12 13
| FileSelector.create(this) .setDefaultFolderIcon(R.drawable.folder_icon) .forResult(new OnResultCallbackListener() { @Override public void onResult(List<FileBean> result) { }
@Override public void onCancel() { } });
|
给指定类型文件添加图标
FileSelector
给小部分常见文件添加了图标,例如jpg
、png
,若对此图标不满足或想添加其他类型文件的图标,可以通过如下方式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| FileSelector.create(this) .addIconBySuffix("jpg", R.drawable.img_icon) .addIconBySuffix("png", R.drawable.img_icon) .addIconBySuffix("mp3", R.drawable.music_icon) .forResult(new OnResultCallbackListener() { @Override public void onResult(List<FileBean> result) { }
@Override public void onCancel() { } });
|
批量添加公用同一图标的文件类型,如下代码将jpg
、png
、webp
的图标设置为R.drawable.img_icon
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| FileSelector.create(this) .addBatchesIconBySuffix( new String[] {"jpg", "png", "webp"}, R.drawable.img_icon) .forResult(new OnResultCallbackListener() { @Override public void onResult(List<FileBean> result) { }
@Override public void onCancel() { } });
|
批量添加,注意后缀名和图标的drawable id
一一对应
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| FileSelector.create(this) .addBatchesIconBySuffix( new String[] {"jpg", "png", "mp3"}, new int[] {R.drawable.img_icon, R.drawable.img_icon, R.drawable.music_icon}) .forResult(new OnResultCallbackListener() { @Override public void onResult(List<FileBean> result) { }
@Override public void onCancel() { } });
|
加载略缩图
开启略缩图加载后,图片、GIF图片以及视频的图标将显示一个略缩图,但是加载略缩图需要加载引擎,可以参考下面使用Glide
实现的GlideEngine
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| FileSelector.create(this) .isDisplayThumbnail(true) .setImageEngine(GlideEngine.createGlideEngine()) .forResult(new OnResultCallbackListener() { @Override public void onResult(List<FileBean> result) { }
@Override public void onCancel() { } });
|
GlideEngine
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| public class GlideEngine implements ImageEngine { private static volatile GlideEngine glideEngine;
private GlideEngine () {}
public static GlideEngine createGlideEngine() { if (glideEngine == null) { synchronized (GlideEngine.class) { if (glideEngine == null) { glideEngine = new GlideEngine(); } } } return glideEngine; }
@Override public void loadFileImage(Context context, File file, ImageView imageView, int defaultDrawableId) { RequestOptions options = new RequestOptions() .centerCrop() .placeholder(defaultDrawableId); Glide.with(context) .load(file) .apply(options) .into(imageView); }
@Override public void loadDocumentFileImage(Context context, DocumentFile documentFile, ImageView imageView, int defaultDrawableId) { RequestOptions options = new RequestOptions() .centerCrop() .placeholder(defaultDrawableId); Glide.with(context) .load(documentFile.getUri()) .apply(options) .into(imageView); } }
|
文件修改时间的格式
FileSelector
中默认的文件修改时间的显示格式是2024-01-01 12:30:26
,可以通过如下方式修改
1 2 3 4 5 6 7 8 9 10 11 12 13
| FileSelector.create(this) .setLastModifiedPattern("yyyy年MM月dd日 HH时mm分ss秒") .forResult(new OnResultCallbackListener() { @Override public void onResult(List<FileBean> result) { }
@Override public void onCancel() { } });
|
只显示文件夹
设置文件列表中只显示文件夹,不显示文件
1 2 3 4 5 6 7 8 9 10 11 12 13
| FileSelector.create(this) .isOnlyDisplayFolder(true) .forResult(new OnResultCallbackListener() { @Override public void onResult(List<FileBean> result) { }
@Override public void onCancel() { } });
|
只选择文件
设置只能选择文件,禁止选择文件夹
1 2 3 4 5 6 7 8 9 10 11 12 13
| FileSelector.create(this) .isOnlySelectFile(true) .forResult(new OnResultCallbackListener() { @Override public void onResult(List<FileBean> result) { }
@Override public void onCancel() { } });
|
显示指定类型文件
设置仅显示指定类型的文件,如下代码设置后,将仅显示jpg
、txt
、mp3
类型的文件
1 2 3 4 5 6 7 8 9 10 11 12 13
| FileSelector.create(this) .addDisplayType("jpg", "txt", "mp3") .forResult(new OnResultCallbackListener() { @Override public void onResult(List<FileBean> result) { }
@Override public void onCancel() { } });
|
设置最大选择数
如下代码设置后,在选择文件时最多只能选择5
个
1 2 3 4 5 6 7 8 9 10 11 12 13
| FileSelector.create(this) .setMaxSelectValue(5) .forResult(new OnResultCallbackListener() { @Override public void onResult(List<FileBean> result) { }
@Override public void onCancel() { } });
|
设置最大选择数支持添加一个文件选择回调,将会在选择item
时调用该回调方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| FileSelector.create(this) .setMaxSelectValue(5, new OnSelectCallBackListener() { @Override public void onSelectCallBack(int maxSelectCount, int currentSelectCount) { if (currentSelectCount >= maxSelectCount) { Toast.makeText(SelectActivity.this, "最多选择" + maxSelectCount + "个文件~", Toast.LENGTH_SHORT).show(); } } }) .forResult(new OnResultCallbackListener() { @Override public void onResult(List<FileBean> result) { }
@Override public void onCancel() { } });
|
设置单选模式
在设置单选模式后,将仅能选择一个文件或文件夹;单选模式不同于设置最大选择数为1,具体区别请自行测试
1 2 3 4 5 6 7 8 9 10 11 12 13
| FileSelector.create(this) .isSingle(true) .forResult(new OnResultCallbackListener() { @Override public void onResult(List<FileBean> result) { }
@Override public void onCancel() { } });
|
开启震动
默认为开启状态,选择文件或文件夹时将轻微震动手机
1 2 3 4 5 6 7 8 9 10 11 12 13
| FileSelector.create(this) .isVibrator(true) .forResult(new OnResultCallbackListener() { @Override public void onResult(List<FileBean> result) { }
@Override public void onCancel() { } });
|
自动打开选择模式
开启后,在进入文件选择页面时将自动打开文件选择模式
1 2 3 4 5 6 7 8 9 10 11 12 13
| FileSelector.create(this) .isAutoOpenSelectMode(true) .forResult(new OnResultCallbackListener() { @Override public void onResult(List<FileBean> result) { }
@Override public void onCancel() { } });
|
设置状态栏颜色
设置状态栏的颜色在fragment
注入模式下同样生效,所以在选择文件之后可能需要重新设置frameLayout
所属Activity
的状态栏颜色
1 2 3 4 5 6 7 8 9 10 11 12 13
| FileSelector.create(this) .setStatusBarColor(R.color.blue) .forResult(new OnResultCallbackListener() { @Override public void onResult(List<FileBean> result) { }
@Override public void onCancel() { } });
|
设置状态栏字体颜色
状态栏字体颜色只有黑色和白色两种,当为true
时状态栏字体颜色将显示黑色
在fragment
注入模式下同样生效,所以在选择文件之后可能需要重新设置frameLayout
所属Activity
的状态栏字体颜色
1 2 3 4 5 6 7 8 9 10 11 12 13
| FileSelector.create(this) .setStatusBarTextColor(true) .forResult(new OnResultCallbackListener() { @Override public void onResult(List<FileBean> result) { }
@Override public void onCancel() { } });
|
设置导航栏颜色
设置底部虚拟导航栏的颜色在fragment
注入模式下同样生效,所以在选择文件之后可能需要重新设置frameLayout
所属Activity
的导航栏颜色
1 2 3 4 5 6 7 8 9 10 11 12 13
| FileSelector.create(this) .setNavigationBarColor(R.color.blue) .forResult(new OnResultCallbackListener() { @Override public void onResult(List<FileBean> result) { }
@Override public void onCancel() { } });
|
进阶使用
1、设置FileSelector
最下面一层view
的样式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| FileSelectorViewStyle fileSelectorViewStyle = new FileSelectorViewStyle(); fileSelectorViewStyle.setBackgroundColorId(R.color.white); fileSelectorViewStyle.setBackgroundDrawableId(R.drawable.background);
FileSelector.create(this) .setFileSelectorViewStyle(fileSelectorViewStyle) .forResult(new OnResultCallbackListener() { @Override public void onResult(List<FileBean> result) { }
@Override public void onCancel() { } });
|
2、设置FileSelector
顶部栏的样式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| FileSelectorTitleBarStyle fileSelectorTitleBarStyle = new FileSelectorTitleBarStyle();
fileSelectorTitleBarStyle.setHeight(50);
fileSelectorTitleBarStyle.setBackgroundColorId(R.color.blue);
fileSelectorTitleBarStyle.setOverImageDrawableId(R.drawable.back);
fileSelectorTitleBarStyle.setTitleText("请选择文件");
fileSelectorTitleBarStyle.setTitleTextSize(20);
fileSelectorTitleBarStyle.setTitleTextColorId(R.color.white);
fileSelectorTitleBarStyle.setStartControlText("取消");
fileSelectorTitleBarStyle.setEndControlText("全选");
fileSelectorTitleBarStyle.setControlTextSize(16);
fileSelectorTitleBarStyle.setControlTextColorId(R.color.white);
FileSelector.create(this) .setFileSelectorTitleBarStyle(fileSelectorTitleBarStyle) .forResult(new OnResultCallbackListener() { @Override public void onResult(List<FileBean> result) { }
@Override public void onCancel() { } });
|
3、设置FileSelector
路径显示栏的样式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| FileSelectorPathBarStyle fileSelectorPathBarStyle = new FileSelectorPathBarStyle();
fileSelectorPathBarStyle.setBackgroundColorId(R.color.white);
fileSelectorPathBarStyle.setHeadItemBackgroundColorId(R.color.blue);
fileSelectorPathBarStyle.setHeadItemTextColorId(R.color.white);
fileSelectorPathBarStyle.setItemBackgroundColorId(R.color.gray);
fileSelectorPathBarStyle.setItemTextColorId(R.color.black);
fileSelectorPathBarStyle.setItemTextSize(16);
fileSelectorPathBarStyle.setArrowImageDrawableId(R.drawable.arrow);
fileSelectorPathBarStyle.setFileCountDescription("文件数量:");
fileSelectorPathBarStyle.setFolderCountDescription("文件夹数量:");
fileSelectorPathBarStyle.setDescriptionColorId(R.color.black);
fileSelectorPathBarStyle.setDescriptionTextSize(16);
FileSelector.create(this) .setFileSelectorPathBatStyle(fileSelectorPathBarStyle) .forResult(new OnResultCallbackListener() { @Override public void onResult(List<FileBean> result) { }
@Override public void onCancel() { } });
|
4、设置FileSelector
列表样式
列表item的宽高、内边距、外边距及下划线,可以通过RecyclerView
的addItemDecoration()
方法设置,ItemDecoration
可以参考下面的LineItemDecoration
和ImageItemDecoration
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
| FileSelectorListViewStyle fileSelectorListViewStyle = new FileSelectorListViewStyle();
fileSelectorListViewStyle.setBackgroundColorId(R.color.white);
fileSelectorListViewStyle.setEmptyFolderDescription("当前文件夹为空");
fileSelectorListViewStyle.setEmptyFolderDescriptionTextColorId(R.color.black);
fileSelectorListViewStyle.setEmptyFolderDescriptionTextSize(20);
fileSelectorListViewStyle.setEmptyFolderBackgroundColorId(R.color.white);
fileSelectorListViewStyle.setLoadProgressDescription("文件加载中...");
fileSelectorListViewStyle.setLoadProgressDescriptionTextColorId(R.color.black);
fileSelectorListViewStyle.setLoadProgressDescriptionTextSize(20);
fileSelectorListViewStyle.setLoadProgressBarColorId(R.color.blue);
fileSelectorListViewStyle.setLoadProgressBackgroundColorId(R.color.white);
fileSelectorListViewStyle.setItemDecoration(new CustomItemDecoration(this));
FileSelectorListViewStyle.FileSelectorListItemStyle fileSelectorListItemStyle = new FileSelectorListViewStyle.FileSelectorListItemStyle();
fileSelectorListItemStyle.setItemBackgroundColorId(R.color.white);
fileSelectorListItemStyle.setItemActionDownBackgroundColorId(R.color.gray);
fileSelectorListItemStyle.setFileNameTextColorId(R.color.black);
fileSelectorListItemStyle.setFileSizeTextSize(16);
fileSelectorListItemStyle.setLastModifiedTextColorId(R.color.gray);
fileSelectorListItemStyle.setLastModifiedTextSize(16);
fileSelectorListItemStyle.setFileSizeTextColorId(R.color.gray);
fileSelectorListItemStyle.setFileSizeTextSize(16);
fileSelectorListItemStyle.setArrowDrawableId(R.drawable.arrow);
fileSelectorListItemStyle.setSelectedDrawableId(R.drawable.selected);
fileSelectorListItemStyle.setDeselectedDrawableId(R.drawable.deselected);
fileSelectorListViewStyle.setFileSelectorListItemStyle(fileSelectorListItemStyle);
FileSelector.create(this) .setFileSelectorListViewStyle(fileSelectorListViewStyle) .forResult(new OnResultCallbackListener() { @Override public void onResult(List<FileBean> result) { }
@Override public void onCancel() { } });
|
LineItemDecoration
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| public class LineItemDecoration extends RecyclerView.ItemDecoration { private final Context context; private final int lineStrokeWidth;
public LineItemDecoration(Context context, int lineStrokeWidth) { this.context = context; this.lineStrokeWidth = lineStrokeWidth; }
@Override public void onDraw(@NonNull Canvas c, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) { super.onDraw(c, parent, state); Paint paint = new Paint(); paint.setColor(context.getResources().getColor(R.color.black)); paint.setStrokeWidth(PixelsUtil.dp2px(lineStrokeWidth, context));
int childCount = parent.getChildCount(); for (int i = 0; i < childCount; i++) { View child = parent.getChildAt(i); c.drawLine(child.getLeft() + 20, child.getBottom(), child.getRight() - 20, child.getBottom(), paint); } }
@Override public void onDrawOver(@NonNull Canvas c, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) { super.onDrawOver(c, parent, state); }
@Override public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) { super.getItemOffsets(outRect, view, parent, state); outRect.set(0, 0, 0, PixelsUtil.dp2px(lineStrokeWidth, context)); view.setPadding(0,0,0,0); RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) view.getLayoutParams(); layoutParams.height = RecyclerView.LayoutParams.WRAP_CONTENT; layoutParams.width = RecyclerView.LayoutParams.MATCH_PARENT; view.setLayoutParams(layoutParams); } }
|
ImageItemDecoration
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| public class ImageItemDecoration extends RecyclerView.ItemDecoration { private final Context context; private final int imageDrawableId;
public ImageItemDecoration(Context context, int imageDrawableId) { this.context = context; this.imageDrawableId = imageDrawableId; }
@Override public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) { super.getItemOffsets(outRect, view, parent, state); int dp10 = PixelsUtil.dp2px(10, context); outRect.set(0, dp10, 0, dp10); }
@Override public void onDraw(@NonNull Canvas c, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) { super.onDraw(c, parent, state); Drawable drawable = ResourcesUtil.getDrawableById(context, imageDrawableId);
Paint paint = new Paint(); paint.setAntiAlias(true);
int childCount = parent.getChildCount(); for (int i = 0; i < childCount - 1; i++) { View child = parent.getChildAt(i);
int dp20 = PixelsUtil.dp2px(20, context);
int left = child.getLeft() + dp20; int top = child.getBottom(); int right = child.getRight() - dp20; int bottom = child.getBottom() + dp20;
drawable.setBounds(left, top, right, bottom); drawable.draw(c); } } }
|
5、设置FileSelector
底部栏样式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| FileSelectorFootBarStyle fileSelectorFootBarStyle = new FileSelectorFootBarStyle();
fileSelectorFootBarStyle.setBackgroundColorId(R.color.gray);
fileSelectorFootBarStyle.setBtnBackgroundColorId(R.color.white);
fileSelectorFootBarStyle.setBtnActionDownBackgroundColorId(R.color.gray);
fileSelectorFootBarStyle.setLeftButtonText("全选");
fileSelectorFootBarStyle.setLeftButtonSelectedAllText("取消全选");
fileSelectorFootBarStyle.setRightButtonText("确定");
fileSelectorFootBarStyle.setButtonTextColorId(R.color.black);
fileSelectorFootBarStyle.setButtonTextSize(16);
FileSelector.create(this) .setFileSelectorFootBarStyle(fileSelectorFootBarStyle) .forResult(new OnResultCallbackListener() { @Override public void onResult(List<FileBean> result) { }
@Override public void onCancel() { } });
|
开源地址
https://github.com/xxinPro/FileSelector