mlhfileselector
Andriod上提供文件或路径选择的第三方库
自动申请存储权限,支持安卓4.4 ~ 13,支持Android/data和Android/obb目录访问,
支持自定义UI,支持SD卡。
(Library that provides file or path selection on Android, automatically apply for storage permission, support Android 4.4 to 13, support Android/data and Android/obb directory access, support custom UI,support SD card.The Keyword:file selector operator android/data android 11 android 13)
为什么选择我
自动申请存储权限,支持 Android4.4 ~ 13,再也不用为了适配各种版本而苦恼了,快速集成,一句代码搞定,完善的文档,支持无 root 权限访问和操作 Android/data 和 Android/obb 目录(适配 Android 13),支持 SD 卡,高度自定义 UI 满足你的所有需求,使用非常灵活,支持国际化,对于 Android 文件选择你只需要关注你的业务代码即可其他的都交给它。
特性
- 自动申请存储权限
- 安卓 4.4 ~ 13
- Android/data 和 Android/obb 目录访问和操作
- SD 卡
- 高度自定义 UI
- 国际化
- 搜索功能
语言(Language)
中文 | English
前言
在开始之前可以给项目一个 Star 吗?非常感谢,你的支持是我唯一的动力。欢迎 Star 和 Issues!
项目地址:
Github 地址
Gitee 地址
demo 演示:
系统版本:Android 13
下载链接:体验 APP
一、快速开始
第 1 步:添加仓库:
-
如果你的项目 Gradle 配置是在
7.0 以下
,需要在build.gradle
文件中加入
allprojects { repositories { ... mavenCentral() maven { url 'https://jitpack.io' } } }
-
如果你的 Gradle 配置是
7.0 及以上
,则需要在settings.gradle
文件中加入
dependencyResolutionManagement { repositories { ... mavenCentral() maven { url 'https://jitpack.io' } } }
第 2 步:添加远程依赖:
dependencies { ... // 请将"版本"替换成具体的版本号,如 1.1.3 implementation 'io.github.molihuan:pathselector:版本' }
第 3 步:基本用法示范:
//如果没有权限会自动申请权限 PathSelector.build(this, MConstants.BUILD_DIALOG)//Dialog构建方式 .setMorePopupItemListeners( new CommonItemListener("OK") { @Override public boolean onClick(View v, List<FileBean> selectedFiles, String currentPath, BasePathSelectFragment pathSelectFragment) { /**取消dialog弹窗 * pathSelectFragment.getSelectConfigData().buildController.getDialogFragment().dismiss(); */ StringBuilder builder = new StringBuilder(); builder.append("you selected:\n"); for (FileBean fileBean : selectedFiles) { builder.append(fileBean.getPath() + "\n"); } Mtools.toast(builder.toString()); return false; } } ) .show();//开始构建
二、基本设置
打开调试模式
//开启调试模式,生产环境请关闭 PathSelectorConfig.setDebug(true); //或者PathSelector.setDebug(true);
1、Activity 构建模式:
//Activity构建方式 PathSelectFragment selector = PathSelector.build(this, MConstants.BUILD_ACTIVITY) .setRequestCode(635) .setMorePopupItemListeners( new CommonItemListener("OK") { @Override public boolean onClick(View v, List<FileBean> selectedFiles, String currentPath, BasePathSelectFragment pathSelectFragment) { StringBuilder builder = new StringBuilder(); builder.append("you selected:\n"); for (FileBean fileBean : selectedFiles) { builder.append(fileBean.getPath() + "\n"); } Mtools.toast(builder.toString()); return false; } } ) .show();
2、Fragment 构建模式:
第 1 步:在你需要显示的布局文件 xml 中使用 FrameLayout 占位
<FrameLayout android:id="@+id/fragment_select_show_area" android:layout_width="wrap_content" android:layout_height="wrap_content" />
第 2 步:编写代码
//获取PathSelectFragment实例然后在onBackPressed中处理返回按钮点击事件 PathSelectFragment selector = PathSelector.build(this, MConstants.BUILD_FRAGMENT) .setFrameLayoutId(R.id.fragment_select_show_area)//加载位置,FrameLayout的ID .setMorePopupItemListeners( new CommonItemListener("OK") { @Override public boolean onClick(View v, List<FileBean> selectedFiles, String currentPath, BasePathSelectFragment pathSelectFragment) { StringBuilder builder = new StringBuilder(); builder.append("you selected:\n"); for (FileBean fileBean : selectedFiles) { builder.append(fileBean.getPath() + "\n"); } Mtools.toast(builder.toString()); return false; } } ) .show();//开始构建
第 3 步:重写 onBackPressed()方法让路径选择器优先处理返回按钮点击事件
非常重要!!!
非常重要!!!
非常重要!!!
重要的事情说三遍
@Override public void onBackPressed() { //让PathSelectFragment先处理返回按钮点击事件 if (selector != null && selector.onBackPressed()) { return; } ...... super.onBackPressed(); }
3、Dialog 构建模式 & 常用设置:
//获取PathSelectFragment实例然后在onBackPressed中处理返回按钮点击事件 PathSelectFragment selector = PathSelector.build(this, MConstants.BUILD_DIALOG) //.setBuildType(MConstants.BUILD_DIALOG)//已经在build中已经设置了 //.setContext(this)//已经在build中已经设置了 .setRootPath("/storage/emulated/0/")//初始路径 .setShowSelectStorageBtn(true)//是否显示内部存储选择按钮 .setShowTitlebarFragment(true)//是否显示标题栏 .setShowTabbarFragment(true)//是否显示面包屑 .setAlwaysShowHandleFragment(true)//是否总是显示长按弹出选项 .setShowFileTypes("", "mp3", "mp4")//只显示(没有后缀)或(后缀为mp3)或(后缀为mp4)的文件 .setSelectFileTypes("", "mp3")//只能选择(没有后缀)或(后缀为mp3)的文件 .setMaxCount(3)//最多可以选择3个文件,默认是-1不限制 .setRadio()//单选 .setSortType(MConstants.SORT_NAME_ASC)//按名称排序 .setTitlebarMainTitle(new FontBean("My Selector"))//设置标题栏主标题,还可以设置字体大小,颜色等 .setTitlebarBG(Color.GREEN)//设置标题栏颜色 .setFileItemListener(//设置文件item点击回调(点击是文件才会回调,如果点击是文件夹则不会) new FileItemListener() { @Override public boolean onClick(View v, FileBean file, String currentPath, BasePathSelectFragment pathSelectFragment) { Mtools.toast("you clicked path:\n" + file.getPath()); return false; } } ) .setMorePopupItemListeners(//设置右上角选项回调 new CommonItemListener("SelectAll") { @Override public boolean onClick(View v, List<FileBean> selectedFiles, String currentPath, BasePathSelectFragment pathSelectFragment) { pathSelectFragment.selectAllFile(true); return false; } }, new CommonItemListener("DeselectAll") { @Override public boolean onClick(View v, List<FileBean> selectedFiles, String currentPath, BasePathSelectFragment pathSelectFragment) { pathSelectFragment.selectAllFile(false); return false; } } ) .setHandleItemListeners(//设置长按弹出选项回调 new CommonItemListener("OK") { @Override public boolean onClick(View v, List<FileBean> selectedFiles, String currentPath, BasePathSelectFragment pathSelectFragment) { StringBuilder builder = new StringBuilder(); builder.append("you selected:\n"); for (FileBean fileBean : selectedFiles) { builder.append(fileBean.getPath() + "\n"); } Mtools.toast(builder.toString()); return false; } }, new CommonItemListener("cancel") { @Override public boolean onClick(View v, List<FileBean> selectedFiles, String currentPath, BasePathSelectFragment pathSelectFragment) { pathSelectFragment.openCloseMultipleMode(false); return false; } } ) .show();
三、高级设置(自定义 UI)
UI 布局:
1、自定义选项样式(以 HandleItem 为例子)
方式 1:通过 FontBean 来设置样式
PathSelectFragment selector = PathSelector.build(this, MConstants.BUILD_DIALOG) .setHandleItemListeners(//设置长按弹出选项回调 //FontBean可以设置文本、字的大小、字的颜色、字左边的图标 //R.drawable.ic_test_mlh是你自己的图片资源id new CommonItemListener(new FontBean("OK", 18, Color.RED, R.drawable.ic_test_mlh)) { @Override public boolean onClick(View v, List<FileBean> selectedFiles, String currentPath, BasePathSelectFragment pathSelectFragment) { Mtools.toast("You Click"); return false; } } ) .show();
什么?这种方式还不能满足你,那么试试方式2
方式 2:重写 CommonItemListener 的 setViewStyle 方法来自定义样式
PathSelectFragment selector = PathSelector.build(this, MConstants.BUILD_DIALOG) .setHandleItemListeners( //重写CommonItemListener的setViewStyle方法来自定义样式 new CommonItemListener("OK") { @Override public boolean setViewStyle(RelativeLayout container, ImageView leftImg, TextView textView) { textView.setTextSize(18); textView.setTextColor(Color.RED); //默认是不显示图标的 leftImg.setVisibility(View.VISIBLE); leftImg.setImageResource(R.drawable.ic_test_mlh); leftImg.getLayoutParams().width = 90; leftImg.getLayoutParams().height = 90; return true; } @Override public boolean onClick(View v, List<FileBean> selectedFiles, String currentPath, BasePathSelectFragment pathSelectFragment) { Mtools.toast("You Click"); return false; } } ) .show();
什么?什么?这种方式还不能满足你,那么你来写UI它来帮你添加,试试高度自定义UI
2、高度自定义 UI(以 Titlebar 为例子):
第 1 步:新建一个布局文件,如:fragment_custom_titlebar.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal"> <Button android:id="@+id/my_btn1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="btn1" /> <Button android:id="@+id/my_btn2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="selectAll" /> </LinearLayout>
第 2 步:新建一个类,如:CustomTitlebarFragment.class 使其继承 AbstractTitlebarFragment 并关联第 1 步中的布局文件
public class CustomTitlebarFragment extends AbstractTitlebarFragment { private Button btn1; private Button btn2; @Override public int setFragmentViewId() { return R.layout.fragment_custom_titlebar; } @Override public void getComponents(View view) { btn1 = view.findViewById(R.id.my_btn1); btn2 = view.findViewById(R.id.my_btn2); btn1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Mtools.toast("The current path is:\n" + psf.getCurrentPath()); } }); btn2.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { psf.selectAllFile(true); } }); } }
第 3 步:编写代码
//获取PathSelectFragment实例然后在onBackPressed中处理返回按钮点击事件 PathSelectFragment selector = PathSelector.build(this, MConstants.BUILD_DIALOG) .setTitlebarFragment(new CustomTitlebarFragment()) .show();
四、接口与方法(尽量看源码,都写了注释,懒得写文档)
IConfigDataBuilder
方法 | 注释 | 备注 |
---|---|---|
setFrameLayoutId(int id) | 设置加载位置 FrameLayoutID | 当构建模式为 MConstants.BUILD_FRAGMENT 时必须设置 |
setRequestCode(int code) | 设置请求码 | 当构建模式为 MConstants.BUILD_ACTIVITY 时必须设置 |
setRootPath(String path) | 设置开始默认路径 | 默认为内部存储根路径 |
setMaxCount(int maxCount) | 设置最大选择数量 | 不设置默认为-1 即无限 |
setShowFileTypes(String... fileTypes) | 设置显示文件类型 | 没有后缀请用"" |
setSelectFileTypes(String... fileTypes) | 设置选择文件类型 | 没有后缀请用"" |
setSortType(int sortType) | 设置排序规则 | 类型请看 MConstants |
setRadio() | 设置单选 | 默认多选 |
setShowSelectStorageBtn(boolean var) | 设置是否显示内部存储选择按钮 | 默认 true |
setShowTitlebarFragment(boolean var) | 是否显示标题栏 | 默认 true |
setShowTabbarFragment(boolean var) | 是否显示面包屑 | 默认 true |
setAlwaysShowHandleFragment(boolean var) | 是否总是显示长按弹出选项 | 默认 false |
setTitlebarMainTitle(FontBean titlebarMainTitle) | 设置标题栏主标题 | 还可以设置字体大小,颜色等 |
setTitlebarBG(Integer titlebarBG) | 设置标题栏背景颜色 | |
setFileItemListener(FileItemListener fileItemListener) | 设置文件 item 点击回调 | 点击是文件才会回调,如果点击是文件夹则不会 |
setMorePopupItemListeners(CommonItemListener... morePopupItemListener) | 设置右上角选项回调 | |
setHandleItemListeners(CommonItemListener... handleItemListener) | 设置长按弹出选项回调 | |
setTitlebarFragment(AbstractTitlebarFragment titlebarFragment) | 设置自定义标题栏 UI | 自己的 Fragment 必须继承 AbstractTitlebarFragment |
setHandleFragment(AbstractHandleFragment handleFragment) | 设置长按弹出自定义 UI | 自己的 Fragment 必须继承 AbstractHandleFragment |
start() | 开始构建 | 必须调用 |
...... | ...... |
五、!!!特别注意 !!!
分区存储
该库以及适配了分区存储,不需要额外适配,你只需要写你的业务代码即可,其他的交给它。
-
注意该库已经在库的
AndroidManifest.xml
中添加了:<!-- 外部存储的写权限 --> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <!-- 安卓11额外权限 --> <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" tools:ignore="ScopedStorage" /> <!-- 已经适配了分区存储特性 --> <application android:preserveLegacyExternalStorage="true" android:requestLegacyExternalStorage="true" >
-
可能会报错:
Execution failed for task ':app:processDebugMainManifest'. > Manifest merger failed with multiple errors, see logs
请在你的项目中的
AndroidManifest.xml
设置一致
版本升级
- 新版本往往解决了旧版本的一些问题、增加了性能、可扩展性......建议升级新版本
- 请注意因为重构了项目导致了旧版本与新版本不兼容。1.0.x 升级 1.1.x 为非兼容升级,请注意学习新的 API
体积过大
-
已经集成了 Blankj/AndroidUtilCode
如果项目对大小有严格要求请自行下载源码并精简 AndroidUtilCode 模块
代码混淆
- 一般来说无需配置,会自动导入混淆规则
特别鸣谢
- getActivity/XXPermissions
- CymChad/BaseRecyclerViewAdapterHelper
- Blankj/AndroidUtilCode
- xuexiangjys/XTask
- ZLYang110/FileSelector
- zzy0516alex/FileSelectorRelease
开源项目以及其依赖项目。
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于