Android文件路徑選擇器
Android上進(jìn)行文件選擇或操作的第三方庫(kù),自動(dòng)申請(qǐng)存儲(chǔ)權(quán)限,支持 Android4.4 ~ 13,再也不用為了適配各種版本而苦惱了,快速集成,一句代碼搞定,完善的文檔,支持無(wú)root權(quán)限訪問(wèn)和操作Android/data和Android/obb目錄(適配Android 13),支持SD卡,高度自定義UI滿足你的所有需求,使用非常靈活,支持國(guó)際化,對(duì)于Android文件選擇你只需要關(guān)注你的業(yè)務(wù)代碼即可其他的都交給它。
特性
- 自動(dòng)申請(qǐng)存儲(chǔ)權(quán)限
- 安卓 4.4 ~ 13
- Android/data和Android/obb目錄訪問(wèn)和操作
- SD卡
- 高度自定義UI
- 國(guó)際化
- 搜索功能
前言
在開始之前可以給項(xiàng)目一個(gè)Star嗎?非常感謝,你的支持是我唯一的動(dòng)力。歡迎Star和Issues!
項(xiàng)目地址:
Github地址
Gitee地址
demo演示:
系統(tǒng)版本:Android 13
下載鏈接:體驗(yàn)APP
一、快速開始
第1步:添加倉(cāng)庫(kù):
-
如果你的項(xiàng)目 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步:添加遠(yuǎn)程依賴:
-
配置完遠(yuǎn)程倉(cāng)庫(kù)后,在項(xiàng)目 app 模塊下的
build.gradle
文件中加入遠(yuǎn)程依賴
dependencies {
...
// 請(qǐng)將"版本"替換成具體的版本號(hào),如 1.1.14
implementation 'io.github.molihuan:pathselector:版本'
}
第3步:基本用法示范:
//如果沒有權(quán)限會(huì)自動(dòng)申請(qǐng)權(quán)限
PathSelector.build(this, MConstants.BUILD_DIALOG)//Dialog構(gòu)建方式
.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();//開始構(gòu)建
二、基本設(shè)置
打開調(diào)試模式
//開啟調(diào)試模式,生產(chǎn)環(huán)境請(qǐng)關(guān)閉
PathSelectorConfig.setDebug(true);
//或者PathSelector.setDebug(true);
1、Activity構(gòu)建模式:
//Activity構(gòu)建方式
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構(gòu)建模式:
第1步:在你需要顯示的布局文件xml中使用FrameLayout占位
<FrameLayout
android:id="@+id/fragment_select_show_area"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
第2步:編寫代碼
//獲取PathSelectFragment實(shí)例然后在onBackPressed中處理返回按鈕點(diǎn)擊事件
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();//開始構(gòu)建
第3步:重寫onBackPressed()方法讓路徑選擇器優(yōu)先處理返回按鈕點(diǎn)擊事件
非常重要!!!
非常重要!!!
非常重要!!!
重要的事情說(shuō)三遍
@Override
public void onBackPressed() {
//讓PathSelectFragment先處理返回按鈕點(diǎn)擊事件
if (selector != null && selector.onBackPressed()) {
return;
}
......
super.onBackPressed();
}
3、Dialog構(gòu)建模式 & 常用設(shè)置:
//獲取PathSelectFragment實(shí)例然后在onBackPressed中處理返回按鈕點(diǎn)擊事件
PathSelectFragment selector = PathSelector.build(this, MConstants.BUILD_DIALOG)
//.setBuildType(MConstants.BUILD_DIALOG)//已經(jīng)在build中已經(jīng)設(shè)置了
//.setContext(this)//已經(jīng)在build中已經(jīng)設(shè)置了
.setRootPath("/storage/emulated/0/")//初始路徑
.setShowSelectStorageBtn(true)//是否顯示內(nèi)部存儲(chǔ)選擇按鈕
.setShowTitlebarFragment(true)//是否顯示標(biāo)題欄
.setShowTabbarFragment(true)//是否顯示面包屑
.setAlwaysShowHandleFragment(true)//是否總是顯示長(zhǎng)按彈出選項(xiàng)
.setShowFileTypes("", "mp3", "mp4")//只顯示(沒有后綴)或(后綴為mp3)或(后綴為mp4)的文件
.setSelectFileTypes("", "mp3")//只能選擇(沒有后綴)或(后綴為mp3)的文件
.setMaxCount(3)//最多可以選擇3個(gè)文件,默認(rèn)是-1不限制
.setRadio()//單選
.setSortType(MConstants.SORT_NAME_ASC)//按名稱排序
.setTitlebarMainTitle(new FontBean("My Selector"))//設(shè)置標(biāo)題欄主標(biāo)題,還可以設(shè)置字體大小,顏色等
.setTitlebarBG(Color.GREEN)//設(shè)置標(biāo)題欄顏色
.setFileItemListener(//設(shè)置文件item點(diǎn)擊回調(diào)(點(diǎn)擊是文件才會(huì)回調(diào),如果點(diǎn)擊是文件夾則不會(huì))
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(//設(shè)置右上角選項(xiàng)回調(diào)
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(//設(shè)置長(zhǎng)按彈出選項(xiàng)回調(diào)
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();
三、高級(jí)設(shè)置(自定義UI)
UI布局:
1、自定義選項(xiàng)樣式(以HandleItem為例子)
方式1:通過(guò)FontBean來(lái)設(shè)置樣式
PathSelectFragment selector = PathSelector.build(this, MConstants.BUILD_DIALOG)
.setHandleItemListeners(//設(shè)置長(zhǎng)按彈出選項(xiàng)回調(diào)
//FontBean可以設(shè)置文本、字的大小、字的顏色、字左邊的圖標(biāo)
//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方法來(lái)自定義樣式
PathSelectFragment selector = PathSelector.build(this, MConstants.BUILD_DIALOG)
.setHandleItemListeners(
//重寫CommonItemListener的setViewStyle方法來(lái)自定義樣式
new CommonItemListener("OK") {
@Override
public boolean setViewStyle(RelativeLayout container, ImageView leftImg, TextView textView) {
textView.setTextSize(18);
textView.setTextColor(Color.RED);
//默認(rèn)是不顯示圖標(biāo)的
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();
什么?什么?這種方式還不能滿足你,那么你來(lái)寫UI它來(lái)幫你添加,試試高度自定義UI
2、高度自定義UI(以Titlebar為例子):
第1步:新建一個(gè)布局文件,如: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步:新建一個(gè)類,如:CustomTitlebarFragment.class使其繼承AbstractTitlebarFragment并關(guān)聯(lián)第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實(shí)例然后在onBackPressed中處理返回按鈕點(diǎn)擊事件
PathSelectFragment selector = PathSelector.build(this, MConstants.BUILD_DIALOG)
.setTitlebarFragment(new CustomTitlebarFragment())
.show();
四、接口與方法(盡量看源碼,都寫了注釋,懶得寫文檔)
IConfigDataBuilder
方法 | 注釋 | 備注 |
---|---|---|
setFrameLayoutId(int id) | 設(shè)置加載位置FrameLayoutID | 當(dāng)構(gòu)建模式為MConstants.BUILD_FRAGMENT時(shí)必須設(shè)置 |
setRequestCode(int code) | 設(shè)置請(qǐng)求碼 | 當(dāng)構(gòu)建模式為MConstants.BUILD_ACTIVITY時(shí)必須設(shè)置 |
setRootPath(String path) | 設(shè)置開始默認(rèn)路徑 | 默認(rèn)為內(nèi)部存儲(chǔ)根路徑 |
setMaxCount(int maxCount) | 設(shè)置最大選擇數(shù)量 | 不設(shè)置默認(rèn)為-1 即無(wú)限 |
setShowFileTypes(String… fileTypes) | 設(shè)置顯示文件類型 | 沒有后綴請(qǐng)用"" |
setSelectFileTypes(String… fileTypes) | 設(shè)置選擇文件類型 | 沒有后綴請(qǐng)用"" |
setSortType(int sortType) | 設(shè)置排序規(guī)則 | 類型請(qǐng)看MConstants |
setRadio() | 設(shè)置單選 | 默認(rèn)多選 |
setShowSelectStorageBtn(boolean var) | 設(shè)置是否顯示內(nèi)部存儲(chǔ)選擇按鈕 | 默認(rèn)true |
setShowTitlebarFragment(boolean var) | 是否顯示標(biāo)題欄 | 默認(rèn)true |
setShowTabbarFragment(boolean var) | 是否顯示面包屑 | 默認(rèn)true |
setAlwaysShowHandleFragment(boolean var) | 是否總是顯示長(zhǎng)按彈出選項(xiàng) | 默認(rèn)false |
setTitlebarMainTitle(FontBean titlebarMainTitle) | 設(shè)置標(biāo)題欄主標(biāo)題 | 還可以設(shè)置字體大小,顏色等 |
setTitlebarBG(Integer titlebarBG) | 設(shè)置標(biāo)題欄背景顏色 | |
setFileItemListener(FileItemListener fileItemListener) | 設(shè)置文件item點(diǎn)擊回調(diào) | 點(diǎn)擊是文件才會(huì)回調(diào),如果點(diǎn)擊是文件夾則不會(huì) |
setMorePopupItemListeners(CommonItemListener… morePopupItemListener) | 設(shè)置右上角選項(xiàng)回調(diào) | |
setHandleItemListeners(CommonItemListener… handleItemListener) | 設(shè)置長(zhǎng)按彈出選項(xiàng)回調(diào) | |
setTitlebarFragment(AbstractTitlebarFragment titlebarFragment) | 設(shè)置自定義標(biāo)題欄UI | 自己的Fragment必須繼承AbstractTitlebarFragment |
setHandleFragment(AbstractHandleFragment handleFragment) | 設(shè)置長(zhǎng)按彈出自定義UI | 自己的Fragment必須繼承AbstractHandleFragment |
start() | 開始構(gòu)建 | 必須調(diào)用 |
… | … |
五、?。?!特別注意 ?。?!
分區(qū)存儲(chǔ)
該庫(kù)以及適配了分區(qū)存儲(chǔ),不需要額外適配,你只需要寫你的業(yè)務(wù)代碼即可,其他的交給它。
-
注意該庫(kù)已經(jīng)在庫(kù)的
AndroidManifest.xml
中添加了:<!-- 外部存儲(chǔ)的寫權(quán)限 --> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <!-- 安卓11額外權(quán)限 --> <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" tools:ignore="ScopedStorage" /> <!-- 已經(jīng)適配了分區(qū)存儲(chǔ)特性 --> <application android:preserveLegacyExternalStorage="true" android:requestLegacyExternalStorage="true" >
-
可能會(huì)報(bào)錯(cuò):
Execution failed for task ':app:processDebugMainManifest'. > Manifest merger failed with multiple errors, see logs
請(qǐng)?jiān)谀愕捻?xiàng)目中的
AndroidManifest.xml
設(shè)置一致
版本升級(jí)
- 新版本往往解決了舊版本的一些問(wèn)題、增加了性能、可擴(kuò)展性…建議升級(jí)新版本
- 請(qǐng)注意因?yàn)橹貥?gòu)了項(xiàng)目導(dǎo)致了舊版本與新版本不兼容。1.0.x升級(jí)1.1.x為非兼容升級(jí),請(qǐng)注意學(xué)習(xí)新的API
體積過(guò)大
-
已經(jīng)集成了Blankj/AndroidUtilCode
如果項(xiàng)目對(duì)大小有嚴(yán)格要求請(qǐng)自行下載源碼并精簡(jiǎn)AndroidUtilCode模塊
代碼混淆
- 一般來(lái)說(shuō)無(wú)需配置,會(huì)自動(dòng)導(dǎo)入混淆規(guī)則
特別鳴謝
-
getActivity/XXPermissions
-
CymChad/BaseRecyclerViewAdapterHelper
-
Blankj/AndroidUtilCode
-
xuexiangjys/XTask
-
ZLYang110/FileSelector
-
zzy0516alex/FileSelectorRelease文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-444329.html
開源項(xiàng)目以及其依賴項(xiàng)目。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-444329.html
到了這里,關(guān)于Android文件選擇器 路徑選擇 支持安卓4.4 ~ 13 支持Android/data目錄訪問(wèn) 支持SD卡 適配Android11的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!