├── .gitignore ├── .idea ├── compiler.xml ├── copyright │ └── profiles_settings.xml ├── gradle.xml ├── misc.xml ├── modules.xml ├── runConfigurations.xml └── vcs.xml ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── github │ │ └── isabsent │ │ └── filepickerdemo │ │ └── MainActivity.java │ └── res │ ├── drawable-hdpi │ └── ic_launcher.png │ ├── drawable-mdpi │ └── ic_launcher.png │ ├── drawable-xhdpi │ └── ic_launcher.png │ ├── drawable-xxhdpi │ └── ic_launcher.png │ ├── drawable-xxxhdpi │ └── ic_launcher.png │ ├── layout │ └── activity_main.xml │ └── values │ ├── colors.xml │ ├── strings.xml │ └── styles.xml ├── build.gradle ├── filepicker ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── github │ │ └── isabsent │ │ └── filepicker │ │ ├── SimpleFilePickerDialog.java │ │ ├── comparator │ │ ├── FileComparator.java │ │ └── FileNameComparator.java │ │ └── entity │ │ ├── Item.java │ │ ├── ItemViewHolder.java │ │ └── SimpleFilePickerItem.java │ └── res │ ├── layout-v17 │ ├── simple_list_item_1.xml │ ├── simple_list_item_multiple_choice.xml │ └── simple_list_item_single_choice.xml │ ├── layout │ ├── simple_list_item_1.xml │ ├── simple_list_item_multiple_choice.xml │ └── simple_list_item_single_choice.xml │ ├── mipmap-hdpi │ ├── ic_folder_black_24dp.png │ └── ic_insert_drive_file_black_24dp.png │ ├── mipmap-mdpi │ ├── ic_folder_black_24dp.png │ └── ic_insert_drive_file_black_24dp.png │ ├── mipmap-xhdpi │ ├── ic_folder_black_24dp.png │ └── ic_insert_drive_file_black_24dp.png │ ├── mipmap-xxhdpi │ ├── ic_folder_black_24dp.png │ └── ic_insert_drive_file_black_24dp.png │ ├── mipmap-xxxhdpi │ ├── ic_folder_black_24dp.png │ └── ic_insert_drive_file_black_24dp.png │ └── values │ ├── colors.xml │ ├── strings.xml │ └── styles.xml ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── screenshot ├── Screenshot_01.png ├── Screenshot_02.png └── Screenshot_03.png └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | .externalNativeBuild 10 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 18 | 19 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 19 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 46 | 47 | 48 | 49 | 50 | 1.8 51 | 52 | 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FilePicker 2 | File and folder picker dialog 3 | 4 | ## Gradle: 5 | 6 | dependencies { 7 | compile 'com.github.isabsent:filepicker:1.1.01' 8 | } 9 | 10 | ## Maven: 11 | 12 | 13 | com.github.isabsent 14 | filepicker 15 | 1.1.01 16 | pom 17 | 18 | 19 | ![FILE_ONLY_SINGLE_CHOICE](https://github.com/isabsent/FilePicker/blob/master/screenshot/Screenshot_01.png) 20 | ![FOLDER_ONLY_MULTI_CHOICE](https://github.com/isabsent/FilePicker/blob/master/screenshot/Screenshot_02.png) 21 | ![FILE_OR_FOLDER_DIRECT_CHOICE_SELECTION](https://github.com/isabsent/FilePicker/blob/master/screenshot/Screenshot_03.png) 22 | 23 | You can explore **internal memory file system** with any of 12 modes: 24 | 25 | FILE_ONLY_SINGLE_CHOICE 26 | FILE_ONLY_MULTI_CHOICE 27 | FILE_ONLY_DIRECT_CHOICE_IMMEDIATE 28 | FILE_ONLY_DIRECT_CHOICE_SELECTION 29 | 30 | FOLDER_ONLY_SINGLE_CHOICE 31 | FOLDER_ONLY_MULTI_CHOICE 32 | FOLDER_ONLY_DIRECT_CHOICE_IMMEDIATE 33 | FOLDER_ONLY_DIRECT_CHOICE_SELECTION 34 | 35 | FILE_OR_FOLDER_SINGLE_CHOICE 36 | FILE_AND_FOLDER_MULTI_CHOICE 37 | FILE_OR_FOLDER_DIRECT_CHOICE_IMMEDIATE 38 | FILE_OR_FOLDER_DIRECT_CHOICE_SELECTION 39 | 40 | 41 | To use this library in your Activity class you have to realize `SimpleFilePickerDialog.InteractionListenerInt` interface if you are defying dialog title as an `int` resource ID: 42 | 43 | @Override 44 | public void showListItemDialog(int titleResId, String folderPath, SimpleFilePickerDialog.CompositeMode mode, String dialogTag){ 45 | SimpleFilePickerDialog.build(folderPath, mode) 46 | .title(titleResId) 47 | .show(this, dialogTag); 48 | } 49 | 50 | or `SimpleFilePickerDialog.InteractionListenerString` interface if you are defying dialog title as a `String`: 51 | 52 | @Override 53 | public void showListItemDialog(String title, String folderPath, SimpleFilePickerDialog.CompositeMode mode, String dialogTag){ 54 | SimpleFilePickerDialog.build(folderPath, mode) 55 | .title(title) 56 | .show(this, dialogTag); 57 | } 58 | or any of two above if you are not specifying a dialog title. A result of selection is available in `onResult` callback: 59 | 60 | @Override 61 | public boolean onResult(@NonNull String dialogTag, int which, @NonNull Bundle extras) { 62 | switch (dialogTag) { 63 | case PICK_DIALOG: 64 | if (extras.containsKey(SimpleFilePickerDialog.SELECTED_SINGLE_PATH)) 65 | //Do what you want with single selection 66 | else if (extras.containsKey(SimpleFilePickerDialog.SELECTED_PATHS)) 67 | //Do what you want with multiple selection 68 | break; 69 | } 70 | return false; 71 | } 72 | 73 | [The example of usage](https://github.com/isabsent/FilePicker/blob/master/app/src/main/java/com/github/isabsent/filepickerdemo/MainActivity.java) 74 | 75 | This library is an extension of [**SimpleDialogFragments**](https://github.com/eltos/SimpleDialogFragments) 76 | 77 | ## License 78 | 79 | Copyright 2018 Lev Popovich (github.com/isabsent) 80 | 81 | Licensed under the Apache License 2.0 82 | 83 | You may only use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software in compliance with the License. For more information visit http://www.apache.org/licenses/LICENSE-2.0 84 | The above copyright notice alongside a copy of the Apache License shall be included in all copies or substantial portions of the Software not only in source code but also in a license listing accessible by the user. 85 | 86 | I would appreciate being notified when you release an application that uses this library. Thanks! 87 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 25 5 | buildToolsVersion "25.0.3" 6 | defaultConfig { 7 | applicationId "com.github.isabsent.filepickerdemo" 8 | minSdkVersion 14 9 | targetSdkVersion 22 10 | versionCode 1 11 | versionName "1.0" 12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | compile fileTree(dir: 'libs', include: ['*.jar']) 24 | compile 'com.android.support:appcompat-v7:25.+' 25 | compile 'com.android.support:design:25.+' 26 | compile project(':filepicker') 27 | } 28 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in C:\Users\1\AppData\Local\Android\Sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | 19 | # Uncomment this to preserve the line number information for 20 | # debugging stack traces. 21 | #-keepattributes SourceFile,LineNumberTable 22 | 23 | # If you keep the line number information, uncomment this to 24 | # hide the original source file name. 25 | #-renamesourcefileattribute SourceFile 26 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/java/com/github/isabsent/filepickerdemo/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.github.isabsent.filepickerdemo; 2 | 3 | import android.os.Environment; 4 | import android.support.annotation.NonNull; 5 | import android.support.v7.app.AppCompatActivity; 6 | import android.os.Bundle; 7 | import android.view.View; 8 | import android.widget.Toast; 9 | 10 | import com.github.isabsent.filepicker.SimpleFilePickerDialog; 11 | 12 | import java.util.List; 13 | 14 | import static com.github.isabsent.filepicker.SimpleFilePickerDialog.CompositeMode.FILE_AND_FOLDER_MULTI_CHOICE; 15 | import static com.github.isabsent.filepicker.SimpleFilePickerDialog.CompositeMode.FILE_ONLY_DIRECT_CHOICE_IMMEDIATE; 16 | import static com.github.isabsent.filepicker.SimpleFilePickerDialog.CompositeMode.FILE_ONLY_DIRECT_CHOICE_SELECTION; 17 | import static com.github.isabsent.filepicker.SimpleFilePickerDialog.CompositeMode.FILE_ONLY_MULTI_CHOICE; 18 | import static com.github.isabsent.filepicker.SimpleFilePickerDialog.CompositeMode.FILE_ONLY_SINGLE_CHOICE; 19 | import static com.github.isabsent.filepicker.SimpleFilePickerDialog.CompositeMode.FILE_OR_FOLDER_DIRECT_CHOICE_IMMEDIATE; 20 | import static com.github.isabsent.filepicker.SimpleFilePickerDialog.CompositeMode.FILE_OR_FOLDER_DIRECT_CHOICE_SELECTION; 21 | import static com.github.isabsent.filepicker.SimpleFilePickerDialog.CompositeMode.FILE_OR_FOLDER_SINGLE_CHOICE; 22 | import static com.github.isabsent.filepicker.SimpleFilePickerDialog.CompositeMode.FOLDER_ONLY_DIRECT_CHOICE_IMMEDIATE; 23 | import static com.github.isabsent.filepicker.SimpleFilePickerDialog.CompositeMode.FOLDER_ONLY_DIRECT_CHOICE_SELECTION; 24 | import static com.github.isabsent.filepicker.SimpleFilePickerDialog.CompositeMode.FOLDER_ONLY_MULTI_CHOICE; 25 | import static com.github.isabsent.filepicker.SimpleFilePickerDialog.CompositeMode.FOLDER_ONLY_SINGLE_CHOICE; 26 | 27 | public class MainActivity extends AppCompatActivity implements 28 | SimpleFilePickerDialog.InteractionListenerString, 29 | SimpleFilePickerDialog.InteractionListenerInt { 30 | 31 | private static final String //If you need to show a few different mode pickers in one activity, 32 | PICK_DIALOG = "PICK_DIALOG"; //you can distinguish them by this tag in onResult callback. 33 | 34 | @Override 35 | public void showListItemDialog(int titleResId, String folderPath, SimpleFilePickerDialog.CompositeMode mode, String dialogTag){ 36 | SimpleFilePickerDialog.build(folderPath, mode) 37 | .title(titleResId) 38 | // .neut("hoch") //Some customization if you need 39 | // .neg("eröffnen") 40 | // .pos("wählen") 41 | // .choiceMin(1); 42 | // .filterable(true, true) 43 | .show(this, dialogTag); 44 | } 45 | 46 | @Override 47 | public void showListItemDialog(String title, String folderPath, SimpleFilePickerDialog.CompositeMode mode, String dialogTag){ 48 | SimpleFilePickerDialog.build(folderPath, mode) 49 | .title(title) 50 | // .neut("hoch") //Some customization if you need 51 | // .neg("eröffnen") 52 | // .pos("wählen") 53 | // .choiceMin(1); 54 | // .filterable(true, true) 55 | .show(this, dialogTag); 56 | } 57 | 58 | @Override 59 | public boolean onResult(@NonNull String dialogTag, int which, @NonNull Bundle extras) { 60 | switch (dialogTag) { 61 | case PICK_DIALOG: 62 | if (extras.containsKey(SimpleFilePickerDialog.SELECTED_SINGLE_PATH)) { 63 | String selectedSinglePath = extras.getString(SimpleFilePickerDialog.SELECTED_SINGLE_PATH); 64 | Toast.makeText(this, "Path selected:\n" + selectedSinglePath, Toast.LENGTH_LONG).show(); 65 | } else if (extras.containsKey(SimpleFilePickerDialog.SELECTED_PATHS)){ 66 | List selectedPaths = extras.getStringArrayList(SimpleFilePickerDialog.SELECTED_PATHS); 67 | showSelectedPathsToast(selectedPaths); 68 | } 69 | break; 70 | // case PICK_DIALOG_OTHER: 71 | // //Do what you want here 72 | // break; 73 | } 74 | return false; 75 | } 76 | 77 | @Override 78 | protected void onCreate(Bundle savedInstanceState) { 79 | super.onCreate(savedInstanceState); 80 | setContentView(R.layout.activity_main); 81 | 82 | final String rootPath = Environment.getExternalStorageDirectory().getAbsolutePath(); 83 | 84 | //Button clicks with all available modes as an usage example: 85 | 86 | //File picker modes 87 | findViewById(R.id.file_single).setOnClickListener(new View.OnClickListener() { 88 | @Override 89 | public void onClick(View view) { 90 | showListItemDialog(R.string.dialog_title_pick_file, rootPath, FILE_ONLY_SINGLE_CHOICE, PICK_DIALOG); 91 | } 92 | }); 93 | 94 | findViewById(R.id.file_multi).setOnClickListener(new View.OnClickListener() { 95 | @Override 96 | public void onClick(View view) { 97 | showListItemDialog(getString(R.string.dialog_title_pick_files), rootPath, FILE_ONLY_MULTI_CHOICE, PICK_DIALOG); 98 | } 99 | }); 100 | 101 | findViewById(R.id.file_direct_immediate).setOnClickListener(new View.OnClickListener() { 102 | @Override 103 | public void onClick(View view) { 104 | showListItemDialog(R.string.dialog_title_pick_file, rootPath, FILE_ONLY_DIRECT_CHOICE_IMMEDIATE, PICK_DIALOG); 105 | } 106 | }); 107 | 108 | findViewById(R.id.file_direct_postponed).setOnClickListener(new View.OnClickListener() { 109 | @Override 110 | public void onClick(View view) { 111 | showListItemDialog(R.string.dialog_title_pick_file, rootPath, FILE_ONLY_DIRECT_CHOICE_SELECTION, PICK_DIALOG); 112 | } 113 | }); 114 | 115 | //Folder picker modes 116 | findViewById(R.id.folder_single).setOnClickListener(new View.OnClickListener() { 117 | @Override 118 | public void onClick(View view) { 119 | showListItemDialog(getString(R.string.dialog_title_pick_folder), rootPath, FOLDER_ONLY_SINGLE_CHOICE, PICK_DIALOG); 120 | } 121 | }); 122 | 123 | findViewById(R.id.folder_multi).setOnClickListener(new View.OnClickListener() { 124 | @Override 125 | public void onClick(View view) { 126 | showListItemDialog(R.string.dialog_title_pick_folders, rootPath, FOLDER_ONLY_MULTI_CHOICE, PICK_DIALOG); 127 | } 128 | }); 129 | 130 | findViewById(R.id.folder_direct_immediate).setOnClickListener(new View.OnClickListener() { 131 | @Override 132 | public void onClick(View view) { 133 | showListItemDialog(getString(R.string.dialog_title_pick_folder), rootPath, FOLDER_ONLY_DIRECT_CHOICE_IMMEDIATE, PICK_DIALOG); 134 | } 135 | }); 136 | 137 | findViewById(R.id.folder_direct_postponed).setOnClickListener(new View.OnClickListener() { 138 | @Override 139 | public void onClick(View view) { 140 | showListItemDialog(getString(R.string.dialog_title_pick_folder), rootPath, FOLDER_ONLY_DIRECT_CHOICE_SELECTION, PICK_DIALOG); 141 | } 142 | }); 143 | 144 | //Mixed picker modes 145 | findViewById(R.id.file_or_folder_single).setOnClickListener(new View.OnClickListener() { 146 | @Override 147 | public void onClick(View view) { 148 | showListItemDialog(R.string.dialog_title_pick_file_or_folder, rootPath, FILE_OR_FOLDER_SINGLE_CHOICE, PICK_DIALOG); 149 | } 150 | }); 151 | 152 | findViewById(R.id.file_and_folder_multi).setOnClickListener(new View.OnClickListener() { 153 | @Override 154 | public void onClick(View view) { 155 | showListItemDialog(getString(R.string.dialog_title_pick_files_and_folders), rootPath, FILE_AND_FOLDER_MULTI_CHOICE, PICK_DIALOG); 156 | } 157 | }); 158 | 159 | findViewById(R.id.file_or_folder_direct_immediate).setOnClickListener(new View.OnClickListener() { 160 | @Override 161 | public void onClick(View view) { 162 | showListItemDialog(R.string.dialog_title_pick_file_or_folder, rootPath, FILE_OR_FOLDER_DIRECT_CHOICE_IMMEDIATE, PICK_DIALOG); 163 | } 164 | }); 165 | 166 | findViewById(R.id.file_or_folder_direct_postponed).setOnClickListener(new View.OnClickListener() { 167 | @Override 168 | public void onClick(View view) { 169 | showListItemDialog(R.string.dialog_title_pick_file_or_folder, rootPath, FILE_OR_FOLDER_DIRECT_CHOICE_SELECTION, PICK_DIALOG); 170 | } 171 | }); 172 | } 173 | 174 | private void showSelectedPathsToast(List selectedPaths){ 175 | if (selectedPaths != null && !selectedPaths.isEmpty()){ 176 | String selectedPathsString = "\n"; 177 | for (String path : selectedPaths) 178 | selectedPathsString += path + "\n"; 179 | Toast.makeText(this, "Paths selected:" + selectedPathsString, Toast.LENGTH_LONG).show(); 180 | } 181 | } 182 | } 183 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/isabsent/FilePicker/ae7f902e0561f43b8da58dae36099a69c72e0038/app/src/main/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/isabsent/FilePicker/ae7f902e0561f43b8da58dae36099a69c72e0038/app/src/main/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/isabsent/FilePicker/ae7f902e0561f43b8da58dae36099a69c72e0038/app/src/main/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/isabsent/FilePicker/ae7f902e0561f43b8da58dae36099a69c72e0038/app/src/main/res/drawable-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/isabsent/FilePicker/ae7f902e0561f43b8da58dae36099a69c72e0038/app/src/main/res/drawable-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 12 | 13 | 21 | 22 | 28 | 29 |