(Provide file or path selection, 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)
- Automatically request storage permissions
- Android 4.4 ~ 13
- Android/data and Android/obb directory access and manipulation
- SD Card
- Highly customizable UI
- Internationalization
- Search function
Can you give the project a Star before starting? Thank you very much, your support is the only thing that keeps me going. Welcome Star and Issues!
Download Links:Experience App
allprojects {
repositories {
...
mavenCentral()
maven { url 'https://jitpack.io' }
}
}
dependencyResolutionManagement {
repositories {
...
mavenCentral()
maven { url 'https://jitpack.io' }
}
}
dependencies {
...
// Please replace "version" with a specific version number, e.g. 1.1.2
implementation 'io.github.molihuan:pathselector:version'
}
//Permissions will be requested automatically if you don't have them
PathSelector.build(this, MConstants.BUILD_DIALOG)//Dialog build mode
.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();//Start building
//Turn on debug mode, please turn off production environment
PathSelectorConfig.setDebug(true);
//or use PathSelector.setDebug(true);
//Activity build mode
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();
<FrameLayout
android:id="@+id/fragment_select_show_area"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
//Get the PathSelectFragment instance and then handle the back button click event in onBackPressed
PathSelectFragment selector = PathSelector.build(this, MConstants.BUILD_FRAGMENT)
.setFrameLayoutId(R.id.fragment_select_show_area)//Load position, ID of FrameLayout
.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();
Step 3: Override the onBackPressed() method to let the path selector take precedence over the return button click event
@Override
public void onBackPressed() {
//Let PathSelectFragment handle the return button click event first
if (selector != null && selector.onBackPressed()) {
return;
}
......
super.onBackPressed();
}
//Get the PathSelectFragment instance and then handle the back button click event in onBackPressed
PathSelectFragment selector = PathSelector.build(this, MConstants.BUILD_DIALOG)
//.setBuildType(MConstants.BUILD_DIALOG)//Already set in the build
//.setContext(this)//Already set in the build
.setRootPath("/storage/emulated/0/")//Initial path
.setShowSelectStorageBtn(true)//Whether to display internal storage selection button
.setShowTitlebarFragment(true)//Whether to display the title bar
.setShowTabbarFragment(true)//Whether to show breadcrumbs
.setAlwaysShowHandleFragment(true)//Whether to always show the long press pop-up option
.setShowFileTypes("", "mp3", "mp4")//Show only files with (no suffix) or (mp3 suffix) or (mp4 suffix)
.setSelectFileTypes("", "mp3")//Only files with (no suffix) or (mp3 suffix) can be selected
.setMaxCount(3)//You can select up to 3 files. The default is - 1 unlimited
.setRadio()//Single choice
.setSortType(MConstants.SORT_NAME_ASC)//Sort by name
.setTitlebarMainTitle(new FontBean("My Selector"))//Set the title bar main title, you can also set the font size, color, etc.
.setTitlebarBG(Color.GREEN)//Set the title bar background color
.setFileItemListener(//Set the callback for the file item click (it will be called back only if it is a file, but not if it is a folder)
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(//Set the top right option callback
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(//Set long press pop-up option callback
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();
PathSelectFragment selector = PathSelector.build(this, MConstants.BUILD_DIALOG)
.setHandleItemListeners(//Set long press pop-up option callback
//FontBean can set the text, the size of the word, the color of the word, and the icon to the left of the word
//R.drawable.ic_test_mlh is your own image resource 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();
PathSelectFragment selector = PathSelector.build(this, MConstants.BUILD_DIALOG)
.setHandleItemListeners(
//Override CommonItemListener's setViewStyle method to customize the style
new CommonItemListener("OK") {
@Override
public boolean setViewStyle(RelativeLayout container, ImageView leftImg, TextView textView) {
textView.setTextSize(18);
textView.setTextColor(Color.RED);
//Icons are not displayed by default
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();
What? What? This way is not enough for you, then you write the UI it to help you add, try the highly customizable UI
<?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>
Step 2: Create a new class such as:CustomTitlebarFragment.class so that it extends AbstractTitlebarFragment and associates the layout file in step 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);
}
});
}
}
//Get the PathSelectFragment instance and then handle the back button click event in onBackPressed
PathSelectFragment selector = PathSelector.build(this, MConstants.BUILD_DIALOG)
.setTitlebarFragment(new CustomTitlebarFragment())
.show();
IV.Interface and methods (try to see the source code, are written comments, lazy to write the document)
Method | Role | Comment |
---|---|---|
setFrameLayoutId(int id) | Set load location FrameLayout ID | Must be set when the build mode is MConstants.BUILD_FRAGMENT |
setRequestCode(int code) | Set request code | Must be set when build mode is MConstants.BUILD_ACTIVITY |
setRootPath(String path) | Set default path to start | Default is the internal storage root path |
setMaxCount(int maxCount) | Set the maximum number of selections | No setting default is -1 i.e. no limit |
setShowFileTypes(String... fileTypes) | Set the display file type | No suffix please use "" |
setSelectFileTypes(String... fileTypes) | Set the selection file type | No suffix please use "" |
setSortType(int sortType) | Set sorting rules | See MConstants for types |
setRadio() | Set radio selection | Default Multiple Choice |
setShowSelectStorageBtn(boolean var) | Set whether to display the internal storage selection button | Default true |
setShowTitlebarFragment(boolean var) | Whether to display the title bar | Default true |
setShowTabbarFragment(boolean var) | Whether to show breadcrumbs | Default true |
setAlwaysShowHandleFragment(boolean var) | Whether to always show the long press pop-up option | Default false |
setTitlebarMainTitle(FontBean titlebarMainTitle) | Set the main title of the title bar | You can also set the font size, color, etc. |
setTitlebarBG(Integer titlebarBG) | Set the title bar background color | |
setFileItemListener(FileItemListener fileItemListener) | Set file item clickback | The callback will be made only if you click on a file, but not if you click on a folder. |
setMorePopupItemListeners(CommonItemListener... morePopupItemListener) | Set the top right option callback | |
setHandleItemListeners(CommonItemListener... handleItemListener) | Set long press popup option callback | |
setTitlebarFragment(AbstractTitlebarFragment titlebarFragment) | Set custom title bar UI | Your own Fragment must extend AbstractTitlebarFragment |
setHandleFragment(AbstractHandleFragment handleFragment) | Set long press to pop up custom UI | Your own Fragment must extend AbstractHandleFragment |
start() | Start building | Must be called |
...... | ...... | ...... |
The library is also adapted to partitioned storage, no additional adaptation is needed, you just need to write your business code and leave the rest to it.
-
Note that the library has been added to the library's
AndroidManifest.xml
:<!-- Write access to external storage --> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <!-- Android 11 extra permissions --> <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" tools:ignore="ScopedStorage" /> <!-- Partitioned storage features have been adapted --> <application android:preserveLegacyExternalStorage="true" android:requestLegacyExternalStorage="true" >
-
Error may be reported:
Execution failed for task ':app:processDebugMainManifest'. > Manifest merger failed with multiple errors, see logs
Please set the
AndroidManifest.xml
in your project to be consistent
- The new version often solves some of the problems of the old version, increases performance, scalability ...... It is recommended to upgrade to a new version
- Please note that the old version is not compatible with the new version due to the refactoring of the project. 1.0.x upgrade 1.1.x is a non-compatible upgrade, please pay attention to learn the new API
-
Already integrated with Blankj/AndroidUtilCode
If the project has strict requirements on size, please download the source code and streamline the AndroidUtilCode module.
- Generally no configuration is required, obfuscation rules are imported automatically
Open source projects and their dependencies.