├── .gitignore ├── .gitignore.bak ├── .idea ├── gradle.xml ├── markdown-navigator.xml ├── markdown-navigator │ └── profiles_settings.xml ├── modules.xml ├── runConfigurations.xml └── vcs.xml ├── README.md ├── README_CH.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── leon │ │ └── filepicker │ │ └── ApplicationTest.java │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── leon │ │ └── filepicker │ │ └── activity │ │ ├── Consant.java │ │ ├── FileFragment.java │ │ ├── FragmengActivity.java │ │ └── MainActivity.java │ └── res │ ├── layout │ ├── activity_fragmeng.xml │ ├── activity_main.xml │ └── fragment_file.xml │ ├── mipmap-hdpi │ └── ic_launcher.png │ ├── mipmap-mdpi │ └── ic_launcher.png │ ├── mipmap-xhdpi │ └── ic_launcher.png │ ├── mipmap-xxhdpi │ ├── ic_launcher.png │ └── title_bar_back.png │ ├── mipmap-xxxhdpi │ └── ic_launcher.png │ ├── values-w820dp │ └── dimens.xml │ └── values │ ├── colors.xml │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── lfilepickerlibrary ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── leon │ │ └── lfilepickerlibrary │ │ └── ApplicationTest.java │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── leon │ │ └── lfilepickerlibrary │ │ ├── LFilePicker.java │ │ ├── adapter │ │ └── PathAdapter.java │ │ ├── filter │ │ └── LFileFilter.java │ │ ├── model │ │ └── ParamEntity.java │ │ ├── ui │ │ └── LFilePickerActivity.java │ │ ├── utils │ │ ├── CloseUtils.java │ │ ├── CompositeFilter.java │ │ ├── Constant.java │ │ ├── FileComparator.java │ │ ├── FileUtils.java │ │ ├── MemoryConstant.java │ │ └── StringUtils.java │ │ └── widget │ │ └── EmptyRecyclerView.java │ └── res │ ├── drawable-v21 │ ├── lfile_back_bg.xml │ └── lfile_btn_bg.xml │ ├── drawable │ ├── back_bg.xml │ ├── btn_bg.xml │ ├── item_bg_selector.xml │ ├── lfile_back_bg.xml │ └── lfile_btn_bg.xml │ ├── layout │ ├── activity_lfile_picker.xml │ ├── lfile_emptyview.xml │ └── lfile_listitem.xml │ ├── menu │ └── menu_main_toolbar.xml │ ├── mipmap-xhdpi │ ├── lfile_back1.png │ ├── lfile_back2.png │ ├── lfile_emptyimg.png │ ├── lfile_file_style_blue.png │ ├── lfile_file_style_green.png │ ├── lfile_file_style_yellow.png │ ├── lfile_folder_style_blue.png │ ├── lfile_folder_style_green.png │ ├── lfile_folder_style_yellow.png │ └── lfile_up.png │ ├── values-w820dp │ └── dimens.xml │ ├── values-zh │ └── values-zh.xml │ ├── values │ ├── colors.xml │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml │ └── xml │ └── provider_paths.xml ├── projectFilesBackup └── .idea │ └── workspace.xml ├── screenshot ├── Screenshot_20170330-132717.png ├── Screenshot_20170330-133458.png ├── Screenshot_20170330-133811.png ├── Screenshot_20170330-133831.png ├── Screenshot_20170330-133836.png ├── Screenshot_20170330-133844.png ├── Screenshot_20170330-134316.png ├── Screenshot_20170330-134327.png ├── Screenshot_20170330-134333.png ├── 操作.gif ├── 简单操作01.gif ├── 简单操作02.gif ├── 简单操作03.gif └── 简单操作04.gif └── 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 | -------------------------------------------------------------------------------- /.gitignore.bak: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 22 | 23 | -------------------------------------------------------------------------------- /.idea/markdown-navigator.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 35 | 36 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /.idea/markdown-navigator/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.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 | ---------- 2 | ### [中文文档](README_CH.md) 3 | This is a lightweight file selector, it can select files by retrieve phone directory. At the same time contains: 4 | 5 | - A variety of interface style 6 | - Support file multiple-choice or radio 7 | - Support the file type filter 8 | - Support the fragments 9 | - custom title text and color 10 | - Internationalization (switch in both Chinese and English) 11 | - Maximum quantity limitation (withMaxNum) 12 | - All or all cancel 13 | - File size filtering 14 | - Default path specified 15 | 16 | ### version update: 17 | #### V1.8.0 18 | #### V1.7.0 19 | - Adds an interface to specify the initial display path. 20 | - The added interface can filter the file size, larger than the specified size, or less than the specified size. 21 | #### V1.6.0 22 | - Add folder path selection 23 | #### V1.5.0 24 | - Select check to avoid duplication of data 25 | - Single mode does not show full selection operation 26 | #### V1.4.0 27 | - Maximum quantity limitation 28 | - All or all cancel 29 | 30 | ### Running effect: 31 | #### dynamic effect(If the picture can't display properly, you can view the screenshot GIF files in the folder) 32 | ![](screenshot/操作.gif) 33 | #### the page: 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | ### Quick to use 45 | #### 1. add reference 46 | compile 'com.leon:lfilepickerlibrary:1.8.0' 47 | 48 | #### 2. add permission 49 | 50 | 51 | 52 | 53 | #### 3. open Activity 54 | int REQUESTCODE_FROM_ACTIVITY = 1000; 55 | new LFilePicker() 56 | .withActivity(MainActivity.this) 57 | .withRequestCode(REQUESTCODE_FROM_ACTIVITY) 58 | .withStartPath("/storage/emulated/0/Download") 59 | .withIsGreater(false) 60 | .withFileSize(500 * 1024) 61 | .start(); 62 | 63 | #### 4. accept the results of the return 64 | 65 | @Override 66 | protected void onActivityResult(int requestCode, int resultCode, Intent data) { 67 | super.onActivityResult(requestCode, resultCode, data); 68 | if (resultCode == RESULT_OK) { 69 | if (requestCode == REQUESTCODE_FROM_ACTIVITY) { 70 | //If it is a file selection mode, you need to get the path collection of all the files selected 71 | //List list = data.getStringArrayListExtra(Constant.RESULT_INFO);//Constant.RESULT_INFO == "paths" 72 | List list = data.getStringArrayListExtra("paths"); 73 | Toast.makeText(getApplicationContext(), "selected " + list.size() , Toast.LENGTH_SHORT).show(); 74 | //If it is a folder selection mode, you need to get the folder path of your choice 75 | String path = data.getStringExtra("path"); 76 | Toast.makeText(getApplicationContext(), "The selected path is:" + path, Toast.LENGTH_SHORT).show(); 77 | } 78 | } 79 | } 80 | 81 | ### Interface methods 82 | #### method statement 83 | | method | statement | 84 | | -------- | --------- | 85 | | withActivity(Activity activity) |bind Activity| 86 | | withFragment(Fragment fragment) |bind Fragment| 87 | | withSupportFragment(Fragment supportFragment)|bind V4 Fragment| 88 | | withRequestCode(int requestCode) |set the request code| 89 | | withTitle(String title) |Set the title| 90 | | withTitleColor(String color) |Set the title color| 91 | | withBackgroundColor(String color) |Set the title background color| 92 | | withIconStyle(int style) |set the list icon style| 93 | | withBackIcon(int backStyle) |set back icon style| 94 | | withFileFilter(String[] arrs) |set the file type filter| 95 | | withMutilyMode(boolean isMutily) |setting a multiple-choice or radio mode| 96 | | withAddText(String text) |set the multiselect mode selected text| 97 | | withNotFoundBooks(String text) |Set the prompt information when no file selected| 98 | | withMaxNum(int num) |Set the max number of files| 99 | | withChooseMode(boolean chooseMode)|Set the folder selection mode, true (default) to select file, false to select folder| 100 | | withStartPath(String path) |Set the initial display path| 101 | | withIsGreater(boolean isGreater) |Set the filter mode,true(default) is greater than the specified size, or false less than the specified size| 102 | | withFileSize(long size) |Set the size of the specified filter file, and if it is 500K, enter 500*1024| 103 | #### Provide style 104 | 105 | **withIconStyle(int style)** Value model: 106 | - Constant.ICON_STYLE_YELLOW 107 | - Constant.ICON_STYLE_BLUE 108 | - Constant.ICON_STYLE_GREEN 109 | 110 | **withBackIcon(int backStyle)** Value model: 111 | - Constant.BACKICON_STYLEONE 112 | - Constant.BACKICON_STYLETWO 113 | - Constant.BACKICON_STYLETHREE 114 | 115 | **withFileFilter(String[] arrs)** Value model: 116 | 117 | withFileFilter(new String[]{".txt", ".png", ".docx"}) 118 | 119 | ### More detailed usage:[简书:LFilePicker---文件选择利器,各种样式有它就够了](http://www.jianshu.com/p/eeb211e190be) 120 | 121 | ### Thanks 122 | - [AndroidUtilCode][1] 123 | - [MaterialFilePicker][2] 124 | 125 | 126 | ---------- 127 | If the library is useful to you, welcome to star or fork! 128 | Welcome to visit [blog] [3] for more articles. 129 | 130 | ## License 131 | 132 | Copyright (C) 2017 leonHua 133 | 134 | Licensed under the Apache License, Version 2.0 (the "License"); 135 | you may not use this file except in compliance with the License. 136 | You may obtain a copy of the License at 137 | 138 | http://www.apache.org/licenses/LICENSE-2.0 139 | 140 | Unless required by applicable law or agreed to in writing, software 141 | distributed under the License is distributed on an "AS IS" BASIS, 142 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 143 | See the License for the specific language governing permissions and 144 | limitations under the License. 145 | 146 | [1]: https://github.com/Blankj/AndroidUtilCode 147 | [2]: https://github.com/nbsp-team/MaterialFilePicker 148 | [3]: https://leonhua.github.io/ 149 | -------------------------------------------------------------------------------- /README_CH.md: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | ## LFilePicker 4 | 5 | ### 因为工作原因,此项目已停止维护,使用前请查看issues是否有不能解决问题。建议查看代码,在代码上根据自己的需求进行改造~~~ 6 | 7 | > 说明:如果发现应用名称被修改,可以参考issues#26 查看解决方案,或者可以自己下载代码依赖改动,目前木有精力改动,如果你改了欢迎提pull,如果不能接受此缺陷,请慎用~ 8 | 9 | 这是一个轻量级的文件选择器,可以检索手机目录选择文件。同时包含: 10 | 11 | - 多种界面风格 12 | - 支持文件多选或者单选 13 | - 支持文件类型过滤 14 | - 支持Fragment启动 15 | - 自定义标题文字和颜色 16 | - 国际化(中英文切换) 17 | - 最大数量限制 18 | - 全选或者全部取消 19 | - 文件夹路径选择 20 | - 文件大小过滤 21 | - 默认路径指定 22 | 23 | 24 | ### 版本更新: 25 | #### V1.8.0 26 | - 修改了资源名称,统一添加前缀 27 | - 增加了标题字体的大小设置 28 | - 增加了通过主题直接修改 标题颜色和后退图标,更多菜单颜色 29 | #### V1.7.0 30 | - 增加接口指定初始显示路径 31 | - 增加接口可以过滤文件大小,大于指定大小或者小于指定大小 32 | #### V1.6.0 33 | - 增加文件夹路径选择 34 | #### V1.5.0 35 | - 全选校验,避免数据重复添加 36 | - 单选模式下不在显示全选操作 37 | #### V1.4.0 38 | - 最大数量限制 (withMaxNum) 39 | - 全选或者全部取消 40 | 41 | ### 运行效果: 42 | #### 动态操作(如果图片无法正常显示,可以查看screenshot文件夹中gif文件) 43 | ![](screenshot/操作.gif) 44 | #### 页面效果: 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | ### 快速使用 56 | #### 1. 添加引用 57 | 58 | compile 'com.leon:lfilepickerlibrary:1.8.0' 59 | 60 | #### 2. 添加文件读写权限 61 | 62 | 63 | 64 | 65 | #### 3. 开启Activity 66 | int REQUESTCODE_FROM_ACTIVITY = 1000; 67 | new LFilePicker() 68 | .withActivity(MainActivity.this) 69 | .withRequestCode(REQUESTCODE_FROM_ACTIVITY) 70 | .withStartPath("/storage/emulated/0/Download")//指定初始显示路径 71 | .withIsGreater(false)//过滤文件大小 小于指定大小的文件 72 | .withFileSize(500 * 1024)//指定文件大小为500K 73 | .start(); 74 | 75 | #### 4. 接收返回结果 76 | 77 | @Override 78 | protected void onActivityResult(int requestCode, int resultCode, Intent data) { 79 | super.onActivityResult(requestCode, resultCode, data); 80 | if (resultCode == RESULT_OK) { 81 | if (requestCode == REQUESTCODE_FROM_ACTIVITY) { 82 | //如果是文件选择模式,需要获取选择的所有文件的路径集合 83 | //List list = data.getStringArrayListExtra(Constant.RESULT_INFO);//Constant.RESULT_INFO == "paths" 84 | List list = data.getStringArrayListExtra("paths"); 85 | Toast.makeText(getApplicationContext(), "选中了" + list.size() + "个文件", Toast.LENGTH_SHORT).show(); 86 | //如果是文件夹选择模式,需要获取选择的文件夹路径 87 | String path = data.getStringExtra("path"); 88 | Toast.makeText(getApplicationContext(), "选中的路径为" + path, Toast.LENGTH_SHORT).show(); 89 | } 90 | } 91 | } 92 | 93 | ### 接口方法 94 | #### 方法说明 95 | | 方法 | 说明 | 96 | | -------- | --------- | 97 | | withActivity(Activity activity) |绑定Activity| 98 | | withFragment(Fragment fragment) |绑定Fragment| 99 | | withSupportFragment(Fragment supportFragment)|绑定V4包Fragment| 100 | | withRequestCode(int requestCode) |设置请求码| 101 | | withTitle(String title) |设置标题文字| 102 | | withTitleColor(String color) |设置标题文字颜色| 103 | | withBackgroundColor(String color) |设置标题背景颜色| 104 | | withIconStyle(int style) |设置列表图标样式| 105 | | withBackIcon(int backStyle) |设置返回图标样式| 106 | | withFileFilter(String[] arrs) |设置文件类型过滤器| 107 | | withMutilyMode(boolean isMutily) |设置多选或单选模式| 108 | | withAddText(String text) |设置多选模式选中文字| 109 | | withNotFoundBooks(String text) |设置没有选中文件时的提示信息| 110 | | withMaxNum(int num)          |设置最大可选文件数量| 111 | | withChooseMode(boolean chooseMode)|设置文件夹选择模式,true(默认)为选择文件,false为选择文件夹| 112 | | withStartPath(String path) |设置初始显示路径| 113 | | withIsGreater(boolean isGreater) |设置过滤方式,true(默认)为大于指定大小,false小于指定大小| 114 | | withFileSize(long size) |设置指定过滤文件大小,如果是500K则输入500*1024| 115 | #### 提供样式 116 | 117 | **withIconStyle(int style)** 取值模式: 118 | - Constant.ICON_STYLE_YELLOW 119 | - Constant.ICON_STYLE_BLUE 120 | - Constant.ICON_STYLE_GREEN 121 | 122 | **withBackIcon(int backStyle)** 取值模式: 123 | - Constant.BACKICON_STYLEONE 124 | - Constant.BACKICON_STYLETWO 125 | - Constant.BACKICON_STYLETHREE 126 | 127 | **withFileFilter(String[] arrs)** 取值模式: 128 | 129 | withFileFilter(new String[]{".txt", ".png", ".docx"}) 130 | 131 | ### 详细使用请参考文章:[简书:LFilePicker---文件选择利器,各种样式有它就够了](http://www.jianshu.com/p/eeb211e190be) 132 | 133 | ### 感谢 134 | - 使用了[AndroidUtilCode][1]中的文件工具类 135 | - 参考了[MaterialFilePicker][2]部分思路 136 | 137 | 138 | ---------- 139 | 如果本库对你有用,欢迎star或者fork! 欢迎访问 [博客][3] 查看更多文章。 140 | 141 | ## License 142 | 143 | Copyright (C) 2017 leonHua 144 | 145 | Licensed under the Apache License, Version 2.0 (the "License"); 146 | you may not use this file except in compliance with the License. 147 | You may obtain a copy of the License at 148 | 149 | http://www.apache.org/licenses/LICENSE-2.0 150 | 151 | Unless required by applicable law or agreed to in writing, software 152 | distributed under the License is distributed on an "AS IS" BASIS, 153 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 154 | See the License for the specific language governing permissions and 155 | limitations under the License. 156 | 157 | [1]: https://github.com/Blankj/AndroidUtilCode 158 | [2]: https://github.com/nbsp-team/MaterialFilePicker 159 | [3]: https://leonhua.github.io/ 160 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 23 5 | buildToolsVersion '25.0.0' 6 | 7 | defaultConfig { 8 | applicationId "com.leon.filepicker" 9 | minSdkVersion 14 10 | targetSdkVersion 23 11 | versionCode 1 12 | versionName "1.0" 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(include: ['*.jar'], dir: 'libs') 24 | compile project(':lfilepickerlibrary') 25 | compile 'com.android.support:appcompat-v7:23.4.0' 26 | compile 'com.android.support:recyclerview-v7:23.4.0' 27 | compile 'com.android.support:support-v4:23.4.0' 28 | } 29 | -------------------------------------------------------------------------------- /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 D:\studioSDK/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 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/leon/filepicker/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.leon.filepicker; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /app/src/main/java/com/leon/filepicker/activity/Consant.java: -------------------------------------------------------------------------------- 1 | package com.leon.filepicker.activity; 2 | 3 | /** 4 | * 作者:Leon 5 | * 时间:2017/3/23 14:51 6 | */ 7 | public class Consant { 8 | public static int REQUESTCODE_FROM_ACTIVITY = 1000; 9 | public static int REQUESTCODE_FROM_FRAGMENT = 1001; 10 | 11 | } 12 | -------------------------------------------------------------------------------- /app/src/main/java/com/leon/filepicker/activity/FileFragment.java: -------------------------------------------------------------------------------- 1 | package com.leon.filepicker.activity; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | import android.os.Bundle; 7 | import android.support.annotation.Nullable; 8 | import android.support.v4.app.Fragment; 9 | import android.view.LayoutInflater; 10 | import android.view.View; 11 | import android.view.ViewGroup; 12 | import android.widget.TextView; 13 | import android.widget.Toast; 14 | 15 | import com.leon.filepicker.R; 16 | import com.leon.lfilepickerlibrary.LFilePicker; 17 | 18 | import java.util.List; 19 | 20 | public class FileFragment extends Fragment { 21 | private FileFragment mFragment; 22 | 23 | private TextView mTv; 24 | 25 | public FileFragment() { 26 | // Required empty public constructor 27 | } 28 | 29 | public static FileFragment newInstance() { 30 | FileFragment fragment = new FileFragment(); 31 | return fragment; 32 | } 33 | 34 | @Override 35 | public void onCreate(Bundle savedInstanceState) { 36 | super.onCreate(savedInstanceState); 37 | } 38 | 39 | @Override 40 | public View onCreateView(LayoutInflater inflater, ViewGroup container, 41 | Bundle savedInstanceState) { 42 | // Inflate the layout for this fragment 43 | return inflater.inflate(R.layout.fragment_file, container, false); 44 | } 45 | 46 | @Override 47 | public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { 48 | super.onViewCreated(view, savedInstanceState); 49 | this.mFragment = this; 50 | mTv = (TextView) view.findViewById(R.id.tv); 51 | mTv.setOnClickListener(new View.OnClickListener() { 52 | @Override 53 | public void onClick(View v) { 54 | new LFilePicker().withSupportFragment(mFragment) 55 | .withRequestCode(Consant.REQUESTCODE_FROM_FRAGMENT) 56 | .withTitleStyle(R.style.TextStyle) 57 | .withTheme(R.style.AppTheme) 58 | .withTitle("Open From Fragment") 59 | .start(); 60 | } 61 | }); 62 | } 63 | 64 | @Override 65 | public void onAttach(Context context) { 66 | super.onAttach(context); 67 | } 68 | 69 | 70 | @Override 71 | public void onActivityResult(int requestCode, int resultCode, Intent data) { 72 | super.onActivityResult(requestCode, resultCode, data); 73 | if (resultCode == Activity.RESULT_OK) { 74 | if (requestCode == Consant.REQUESTCODE_FROM_FRAGMENT) { 75 | List list = data.getStringArrayListExtra("paths"); 76 | for (String s : list) { 77 | Toast.makeText(getActivity(), s, Toast.LENGTH_SHORT).show(); 78 | } 79 | } 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /app/src/main/java/com/leon/filepicker/activity/FragmengActivity.java: -------------------------------------------------------------------------------- 1 | package com.leon.filepicker.activity; 2 | 3 | import android.content.Intent; 4 | import android.os.Bundle; 5 | import android.support.v4.app.FragmentManager; 6 | import android.support.v4.app.FragmentTransaction; 7 | import android.support.v7.app.AppCompatActivity; 8 | import android.widget.RelativeLayout; 9 | import android.widget.Toast; 10 | 11 | import com.leon.filepicker.R; 12 | 13 | import java.util.List; 14 | 15 | public class FragmengActivity extends AppCompatActivity { 16 | RelativeLayout mRootLayout; 17 | 18 | @Override 19 | protected void onCreate(Bundle savedInstanceState) { 20 | super.onCreate(savedInstanceState); 21 | setContentView(R.layout.activity_fragmeng); 22 | mRootLayout = (RelativeLayout) findViewById(R.id.rootlayout); 23 | FragmentManager manager = getSupportFragmentManager(); 24 | FragmentTransaction transaction = manager.beginTransaction(); 25 | FileFragment fileFragment = FileFragment.newInstance(); 26 | transaction.replace(R.id.rootlayout, fileFragment); 27 | transaction.commit(); 28 | 29 | 30 | } 31 | @Override 32 | protected void onActivityResult(int requestCode, int resultCode, Intent data) { 33 | super.onActivityResult(requestCode, resultCode, data); 34 | 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /app/src/main/java/com/leon/filepicker/activity/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.leon.filepicker.activity; 2 | 3 | import android.Manifest; 4 | import android.app.AlertDialog; 5 | import android.content.DialogInterface; 6 | import android.content.Intent; 7 | import android.content.pm.PackageManager; 8 | import android.os.Build; 9 | import android.os.Bundle; 10 | import android.support.annotation.NonNull; 11 | import android.support.v7.app.AppCompatActivity; 12 | import android.util.Log; 13 | import android.view.View; 14 | import android.widget.RadioGroup; 15 | import android.widget.Toast; 16 | 17 | import com.leon.filepicker.R; 18 | import com.leon.lfilepickerlibrary.LFilePicker; 19 | import com.leon.lfilepickerlibrary.utils.Constant; 20 | 21 | import java.util.ArrayList; 22 | import java.util.List; 23 | 24 | public class MainActivity extends AppCompatActivity { 25 | private static final int CODE_PERMISSIONS = 1; 26 | private final String TAG = "FilePickerLeon"; 27 | private RadioGroup mRgIconType; 28 | private RadioGroup mRgBackArrawType; 29 | private int mIconType; 30 | private int mBackArrawType; 31 | 32 | 33 | @Override 34 | protected void onCreate(Bundle savedInstanceState) { 35 | super.onCreate(savedInstanceState); 36 | setContentView(R.layout.activity_main); 37 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 38 | requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, CODE_PERMISSIONS); 39 | } 40 | initView(); 41 | initListener(); 42 | } 43 | 44 | 45 | private void initView() { 46 | mRgIconType = (RadioGroup) findViewById(R.id.rg_iconstyle); 47 | mRgBackArrawType = (RadioGroup) findViewById(R.id.rg_backarrawstyle); 48 | } 49 | 50 | private void initListener() { 51 | mRgIconType.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() { 52 | @Override 53 | public void onCheckedChanged(RadioGroup group, int checkedId) { 54 | switch (checkedId) { 55 | case R.id.radio_yellow: 56 | mIconType = Constant.ICON_STYLE_YELLOW; 57 | break; 58 | case R.id.radio_green: 59 | mIconType = Constant.ICON_STYLE_GREEN; 60 | break; 61 | case R.id.radio_blue: 62 | mIconType = Constant.ICON_STYLE_BLUE; 63 | break; 64 | } 65 | } 66 | }); 67 | mRgBackArrawType.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() { 68 | @Override 69 | public void onCheckedChanged(RadioGroup group, int checkedId) { 70 | switch (checkedId) { 71 | case R.id.arrawback_styleone: 72 | mBackArrawType = Constant.BACKICON_STYLEONE; 73 | break; 74 | case R.id.arrawback_styletwo: 75 | mBackArrawType = Constant.BACKICON_STYLETWO; 76 | break; 77 | case R.id.arrawback_stylethree: 78 | mBackArrawType = Constant.BACKICON_STYLETHREE; 79 | break; 80 | } 81 | } 82 | }); 83 | } 84 | 85 | public void openFromActivity(View view) { 86 | new LFilePicker() 87 | .withActivity(this) 88 | .withRequestCode(Consant.REQUESTCODE_FROM_ACTIVITY) 89 | .withTitle("文件选择") 90 | .withIconStyle(mIconType) 91 | .withBackIcon(mBackArrawType) 92 | .withMutilyMode(false) 93 | .withMaxNum(2) 94 | .withStartPath("/storage/emulated/0/Download")//指定初始显示路径 95 | .withNotFoundBooks("至少选择一个文件") 96 | .withIsGreater(false)//过滤文件大小 小于指定大小的文件 97 | .withFileSize(500 * 1024)//指定文件大小为500K 98 | .withChooseMode(false)//文件夹选择模式 99 | //.withFileFilter(new String[]{"txt", "png", "docx"}) 100 | .start(); 101 | } 102 | 103 | public void openFragmentActivity(View view) { 104 | startActivity(new Intent(this, FragmengActivity.class)); 105 | } 106 | 107 | @Override 108 | protected void onActivityResult(int requestCode, int resultCode, Intent data) { 109 | super.onActivityResult(requestCode, resultCode, data); 110 | if (resultCode == RESULT_OK) { 111 | if (requestCode == Consant.REQUESTCODE_FROM_ACTIVITY) { 112 | List list = data.getStringArrayListExtra(Constant.RESULT_INFO); 113 | //for (String s : list) { 114 | // Toast.makeText(getApplicationContext(), s, Toast.LENGTH_SHORT).show(); 115 | //} 116 | // Toast.makeText(getApplicationContext(), "选中了" + list.size() + "个文件", Toast.LENGTH_SHORT).show(); 117 | String path = data.getStringExtra("path"); 118 | Toast.makeText(getApplicationContext(), "选中的路径为" + path, Toast.LENGTH_SHORT).show(); 119 | Log.i("LeonFilePicker", path); 120 | } 121 | } 122 | } 123 | 124 | @Override 125 | public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { 126 | super.onRequestPermissionsResult(requestCode, permissions, grantResults); 127 | if (requestCode == CODE_PERMISSIONS && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 128 | List list = new ArrayList<>(); 129 | for (int i = 0; i < grantResults.length; i++) { 130 | if (grantResults[i] == PackageManager.PERMISSION_DENIED) { 131 | list.add(permissions[i]); 132 | } 133 | } 134 | int length = list.size(); 135 | if (length != 0) { 136 | final String[] array = new String[length]; 137 | list.toArray(array); 138 | new AlertDialog.Builder(this) 139 | .setMessage("为了正常使用软件,必须允许这些权限!") 140 | .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { 141 | @Override 142 | public void onClick(DialogInterface dialog, int which) { 143 | requestPermissions(array, CODE_PERMISSIONS); 144 | } 145 | }) 146 | .show(); 147 | } 148 | } 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_fragmeng.xml: -------------------------------------------------------------------------------- 1 | 2 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 16 | 17 | 26 | 27 | 28 | 33 | 34 | 43 | 44 | 45 | 48 | 49 | 53 | 54 | 58 | 59 | 63 | 64 | 65 | 68 | 69 | 73 | 74 | 78 | 79 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_file.xml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 14 | 15 | 25 | 26 | 27 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonHua/LFilePicker/cf668428c50a2a4bc8d06907c02343373b982f3d/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonHua/LFilePicker/cf668428c50a2a4bc8d06907c02343373b982f3d/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonHua/LFilePicker/cf668428c50a2a4bc8d06907c02343373b982f3d/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonHua/LFilePicker/cf668428c50a2a4bc8d06907c02343373b982f3d/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/title_bar_back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonHua/LFilePicker/cf668428c50a2a4bc8d06907c02343373b982f3d/app/src/main/res/mipmap-xxhdpi/title_bar_back.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonHua/LFilePicker/cf668428c50a2a4bc8d06907c02343373b982f3d/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/values-w820dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 64dp 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #B9A7C2 4 | #B9A7C2 5 | #8C95AA 6 | #aaaaaa 7 | #dddddd 8 | #fff 9 | #B9A7C2 10 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 16dp 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | LFilePickDemo 3 | 4 | 5 | Hello blank fragment 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 16 | 17 | 18 | 22 | 23 | 28 | 29 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | repositories { 5 | jcenter() 6 | google() 7 | } 8 | dependencies { 9 | classpath 'com.android.tools.build:gradle:3.5.0' 10 | 11 | // NOTE: Do not place your application dependencies here; they belong 12 | // in the individual module build.gradle files 13 | } 14 | } 15 | 16 | allprojects { 17 | repositories { 18 | jcenter() 19 | google() 20 | } 21 | } 22 | 23 | task clean(type: Delete) { 24 | delete rootProject.buildDir 25 | } 26 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | ## Project-wide Gradle settings. 2 | # 3 | # For more details on how to configure your build environment visit 4 | # http://www.gradle.org/docs/current/userguide/build_environment.html 5 | # 6 | # Specifies the JVM arguments used for the daemon process. 7 | # The setting is particularly useful for tweaking memory settings. 8 | # Default value: -Xmx1024m -XX:MaxPermSize=256m 9 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 10 | # 11 | # When configured, Gradle will run in incubating parallel mode. 12 | # This option should only be used with decoupled projects. More details, visit 13 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 14 | # org.gradle.parallel=true 15 | #Thu Jun 15 08:49:59 CST 2017 16 | systemProp.http.proxyHost=127.0.0.1 17 | systemProp.http.proxyPort=1080 18 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonHua/LFilePicker/cf668428c50a2a4bc8d06907c02343373b982f3d/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Tue Sep 24 18:02:26 CST 2019 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # Attempt to set APP_HOME 46 | # Resolve links: $0 may be a link 47 | PRG="$0" 48 | # Need this for relative symlinks. 49 | while [ -h "$PRG" ] ; do 50 | ls=`ls -ld "$PRG"` 51 | link=`expr "$ls" : '.*-> \(.*\)$'` 52 | if expr "$link" : '/.*' > /dev/null; then 53 | PRG="$link" 54 | else 55 | PRG=`dirname "$PRG"`"/$link" 56 | fi 57 | done 58 | SAVED="`pwd`" 59 | cd "`dirname \"$PRG\"`/" >/dev/null 60 | APP_HOME="`pwd -P`" 61 | cd "$SAVED" >/dev/null 62 | 63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 64 | 65 | # Determine the Java command to use to start the JVM. 66 | if [ -n "$JAVA_HOME" ] ; then 67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 68 | # IBM's JDK on AIX uses strange locations for the executables 69 | JAVACMD="$JAVA_HOME/jre/sh/java" 70 | else 71 | JAVACMD="$JAVA_HOME/bin/java" 72 | fi 73 | if [ ! -x "$JAVACMD" ] ; then 74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 75 | 76 | Please set the JAVA_HOME variable in your environment to match the 77 | location of your Java installation." 78 | fi 79 | else 80 | JAVACMD="java" 81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 82 | 83 | Please set the JAVA_HOME variable in your environment to match the 84 | location of your Java installation." 85 | fi 86 | 87 | # Increase the maximum file descriptors if we can. 88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 89 | MAX_FD_LIMIT=`ulimit -H -n` 90 | if [ $? -eq 0 ] ; then 91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 92 | MAX_FD="$MAX_FD_LIMIT" 93 | fi 94 | ulimit -n $MAX_FD 95 | if [ $? -ne 0 ] ; then 96 | warn "Could not set maximum file descriptor limit: $MAX_FD" 97 | fi 98 | else 99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 100 | fi 101 | fi 102 | 103 | # For Darwin, add options to specify how the application appears in the dock 104 | if $darwin; then 105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 106 | fi 107 | 108 | # For Cygwin, switch paths to Windows format before running java 109 | if $cygwin ; then 110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 112 | JAVACMD=`cygpath --unix "$JAVACMD"` 113 | 114 | # We build the pattern for arguments to be converted via cygpath 115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 116 | SEP="" 117 | for dir in $ROOTDIRSRAW ; do 118 | ROOTDIRS="$ROOTDIRS$SEP$dir" 119 | SEP="|" 120 | done 121 | OURCYGPATTERN="(^($ROOTDIRS))" 122 | # Add a user-defined pattern to the cygpath arguments 123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 125 | fi 126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 127 | i=0 128 | for arg in "$@" ; do 129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 131 | 132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 134 | else 135 | eval `echo args$i`="\"$arg\"" 136 | fi 137 | i=$((i+1)) 138 | done 139 | case $i in 140 | (0) set -- ;; 141 | (1) set -- "$args0" ;; 142 | (2) set -- "$args0" "$args1" ;; 143 | (3) set -- "$args0" "$args1" "$args2" ;; 144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 150 | esac 151 | fi 152 | 153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 154 | function splitJvmOpts() { 155 | JVM_OPTS=("$@") 156 | } 157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 159 | 160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 161 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /lfilepickerlibrary/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /lfilepickerlibrary/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion 23 5 | buildToolsVersion '25.0.0' 6 | 7 | defaultConfig { 8 | minSdkVersion 14 9 | targetSdkVersion 23 10 | versionCode 1 11 | versionName "1.0" 12 | } 13 | buildTypes { 14 | release { 15 | minifyEnabled false 16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 17 | } 18 | } 19 | } 20 | 21 | dependencies { 22 | compile fileTree(include: ['*.jar'], dir: 'libs') 23 | compile 'com.android.support:appcompat-v7:23.4.0' 24 | compile 'com.android.support:recyclerview-v7:23.4.0' 25 | } 26 | -------------------------------------------------------------------------------- /lfilepickerlibrary/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 D:\studioSDK/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 | -------------------------------------------------------------------------------- /lfilepickerlibrary/src/androidTest/java/com/leon/lfilepickerlibrary/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.leon.lfilepickerlibrary; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /lfilepickerlibrary/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 11 | 12 | 17 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /lfilepickerlibrary/src/main/java/com/leon/lfilepickerlibrary/LFilePicker.java: -------------------------------------------------------------------------------- 1 | package com.leon.lfilepickerlibrary; 2 | 3 | import android.app.Activity; 4 | import android.app.Fragment; 5 | import android.content.Intent; 6 | import android.os.Bundle; 7 | import android.support.annotation.NonNull; 8 | import android.support.annotation.StyleRes; 9 | 10 | import com.leon.lfilepickerlibrary.model.ParamEntity; 11 | import com.leon.lfilepickerlibrary.ui.LFilePickerActivity; 12 | 13 | /** 14 | * 作者:Leon 15 | * 时间:2017/3/20 16:57 16 | */ 17 | public class LFilePicker { 18 | private Activity mActivity; 19 | private Fragment mFragment; 20 | private android.support.v4.app.Fragment mSupportFragment; 21 | private String mTitle; 22 | private String mTitleColor; 23 | private int theme = R.style.LFileTheme; 24 | private int mTitleStyle = R.style.LFileToolbarTextStyle; 25 | private String mBackgroundColor; 26 | private int mBackStyle; 27 | private int mRequestCode; 28 | private boolean mMutilyMode = true; 29 | private boolean mChooseMode = true; 30 | private String mAddText; 31 | private int mIconStyle; 32 | private String[] mFileTypes; 33 | private String mNotFoundFiles; 34 | private int mMaxNum; 35 | private String mStartPath; 36 | private boolean mIsGreater = true;//是否大于 37 | private long mFileSize; 38 | 39 | /** 40 | * 绑定Activity 41 | * 42 | * @param activity 43 | * @return 44 | */ 45 | public LFilePicker withActivity(Activity activity) { 46 | this.mActivity = activity; 47 | return this; 48 | } 49 | 50 | /** 51 | * 绑定Fragment 52 | * 53 | * @param fragment 54 | * @return 55 | */ 56 | public LFilePicker withFragment(Fragment fragment) { 57 | this.mFragment = fragment; 58 | return this; 59 | } 60 | 61 | /** 62 | * 绑定v4包Fragment 63 | * 64 | * @param supportFragment 65 | * @return 66 | */ 67 | public LFilePicker withSupportFragment(android.support.v4.app.Fragment supportFragment) { 68 | this.mSupportFragment = supportFragment; 69 | return this; 70 | } 71 | 72 | 73 | /** 74 | * 设置主标题 75 | * 76 | * @param title 77 | * @return 78 | */ 79 | public LFilePicker withTitle(String title) { 80 | this.mTitle = title; 81 | return this; 82 | } 83 | 84 | /** 85 | * 设置标题颜色 86 | * 87 | * @param color 88 | * @return 89 | */ 90 | @Deprecated 91 | public LFilePicker withTitleColor(String color) { 92 | this.mTitleColor = color; 93 | return this; 94 | } 95 | 96 | /** 97 | * 设置主题 98 | * 99 | * @param theme 100 | * @return 101 | */ 102 | public LFilePicker withTheme(@StyleRes int theme) { 103 | this.theme = theme; 104 | return this; 105 | } 106 | 107 | /** 108 | * 设置标题的颜色和字体大小 109 | * 110 | * @param style 111 | * @return 112 | */ 113 | public LFilePicker withTitleStyle(@StyleRes int style) { 114 | this.mTitleStyle = style; 115 | return this; 116 | } 117 | 118 | /** 119 | * 设置背景色 120 | * 121 | * @param color 122 | * @return 123 | */ 124 | public LFilePicker withBackgroundColor(String color) { 125 | this.mBackgroundColor = color; 126 | return this; 127 | } 128 | 129 | /** 130 | * 请求码 131 | * 132 | * @param requestCode 133 | * @return 134 | */ 135 | public LFilePicker withRequestCode(int requestCode) { 136 | this.mRequestCode = requestCode; 137 | return this; 138 | } 139 | 140 | /** 141 | * 设置返回图标 142 | * 143 | * @param backStyle 144 | * @return 145 | */ 146 | public LFilePicker withBackIcon(int backStyle) { 147 | this.mBackStyle = backStyle; 148 | return this; 149 | } 150 | 151 | /** 152 | * 设置选择模式,默认为true,多选;false为单选 153 | * 154 | * @param isMutily 155 | * @return 156 | */ 157 | public LFilePicker withMutilyMode(boolean isMutily) { 158 | this.mMutilyMode = isMutily; 159 | return this; 160 | } 161 | 162 | /** 163 | * 设置多选时按钮文字 164 | * 165 | * @param text 166 | * @return 167 | */ 168 | public LFilePicker withAddText(String text) { 169 | this.mAddText = text; 170 | return this; 171 | } 172 | 173 | /** 174 | * 设置文件夹图标风格 175 | * 176 | * @param style 177 | * @return 178 | */ 179 | public LFilePicker withIconStyle(int style) { 180 | this.mIconStyle = style; 181 | return this; 182 | } 183 | 184 | public LFilePicker withFileFilter(String[] arrs) { 185 | this.mFileTypes = arrs; 186 | return this; 187 | } 188 | 189 | /** 190 | * 没有选中文件时的提示信息 191 | * 192 | * @param notFoundFiles 193 | * @return 194 | */ 195 | public LFilePicker withNotFoundBooks(String notFoundFiles) { 196 | this.mNotFoundFiles = notFoundFiles; 197 | return this; 198 | } 199 | 200 | /** 201 | * 设置最大选中数量 202 | * 203 | * @param num 204 | * @return 205 | */ 206 | public LFilePicker withMaxNum(int num) { 207 | this.mMaxNum = num; 208 | return this; 209 | } 210 | 211 | /** 212 | * 设置初始显示路径 213 | * 214 | * @param path 215 | * @return 216 | */ 217 | public LFilePicker withStartPath(String path) { 218 | this.mStartPath = path; 219 | return this; 220 | } 221 | 222 | /** 223 | * 设置选择模式,true为文件选择模式,false为文件夹选择模式,默认为true 224 | * 225 | * @param chooseMode 226 | * @return 227 | */ 228 | public LFilePicker withChooseMode(boolean chooseMode) { 229 | this.mChooseMode = chooseMode; 230 | return this; 231 | } 232 | 233 | /** 234 | * 设置文件大小过滤方式:大于指定大小或者小于指定大小 235 | * 236 | * @param isGreater true:大于 ;false:小于,同时包含指定大小在内 237 | * @return 238 | */ 239 | public LFilePicker withIsGreater(boolean isGreater) { 240 | this.mIsGreater = isGreater; 241 | return this; 242 | } 243 | 244 | /** 245 | * 设置过滤文件大小 246 | * 247 | * @param fileSize 248 | * @return 249 | */ 250 | public LFilePicker withFileSize(long fileSize) { 251 | this.mFileSize = fileSize; 252 | return this; 253 | } 254 | 255 | public void start() { 256 | if (mActivity == null && mFragment == null && mSupportFragment == null) { 257 | throw new RuntimeException("You must pass Activity or Fragment by withActivity or withFragment or withSupportFragment method"); 258 | } 259 | Intent intent = initIntent(); 260 | Bundle bundle = getBundle(); 261 | intent.putExtras(bundle); 262 | 263 | if (mActivity != null) { 264 | mActivity.startActivityForResult(intent, mRequestCode); 265 | } else if (mFragment != null) { 266 | mFragment.startActivityForResult(intent, mRequestCode); 267 | } else { 268 | mSupportFragment.startActivityForResult(intent, mRequestCode); 269 | } 270 | } 271 | 272 | 273 | private Intent initIntent() { 274 | Intent intent; 275 | if (mActivity != null) { 276 | intent = new Intent(mActivity, LFilePickerActivity.class); 277 | } else if (mFragment != null) { 278 | intent = new Intent(mFragment.getActivity(), LFilePickerActivity.class); 279 | } else { 280 | intent = new Intent(mSupportFragment.getActivity(), LFilePickerActivity.class); 281 | } 282 | return intent; 283 | } 284 | 285 | @NonNull 286 | private Bundle getBundle() { 287 | ParamEntity paramEntity = new ParamEntity(); 288 | paramEntity.setTitle(mTitle); 289 | paramEntity.setTheme(theme); 290 | paramEntity.setTitleColor(mTitleColor); 291 | paramEntity.setTitleStyle(mTitleStyle); 292 | paramEntity.setBackgroundColor(mBackgroundColor); 293 | paramEntity.setBackIcon(mBackStyle); 294 | paramEntity.setMutilyMode(mMutilyMode); 295 | paramEntity.setAddText(mAddText); 296 | paramEntity.setIconStyle(mIconStyle); 297 | paramEntity.setFileTypes(mFileTypes); 298 | paramEntity.setNotFoundFiles(mNotFoundFiles); 299 | paramEntity.setMaxNum(mMaxNum); 300 | paramEntity.setChooseMode(mChooseMode); 301 | paramEntity.setPath(mStartPath); 302 | paramEntity.setFileSize(mFileSize); 303 | paramEntity.setGreater(mIsGreater); 304 | Bundle bundle = new Bundle(); 305 | bundle.putSerializable("param", paramEntity); 306 | return bundle; 307 | } 308 | } 309 | -------------------------------------------------------------------------------- /lfilepickerlibrary/src/main/java/com/leon/lfilepickerlibrary/adapter/PathAdapter.java: -------------------------------------------------------------------------------- 1 | package com.leon.lfilepickerlibrary.adapter; 2 | 3 | import android.content.Context; 4 | import android.support.v7.widget.RecyclerView; 5 | import android.view.View; 6 | import android.view.ViewGroup; 7 | import android.widget.CheckBox; 8 | import android.widget.CompoundButton; 9 | import android.widget.ImageView; 10 | import android.widget.RelativeLayout; 11 | import android.widget.TextView; 12 | 13 | import com.leon.lfilepickerlibrary.R; 14 | import com.leon.lfilepickerlibrary.utils.Constant; 15 | import com.leon.lfilepickerlibrary.utils.FileUtils; 16 | 17 | import java.io.File; 18 | import java.io.FileFilter; 19 | import java.util.List; 20 | 21 | /** 22 | * 作者:Leon 23 | * 时间:2017/3/15 15:47 24 | */ 25 | public class PathAdapter extends RecyclerView.Adapter { 26 | public interface OnItemClickListener { 27 | void click(int position); 28 | } 29 | 30 | public interface OnCancelChoosedListener { 31 | void cancelChoosed(CheckBox checkBox); 32 | } 33 | 34 | private final String TAG = "FilePickerLeon"; 35 | private List mListData; 36 | private Context mContext; 37 | public OnItemClickListener onItemClickListener; 38 | private FileFilter mFileFilter; 39 | private boolean[] mCheckedFlags; 40 | private boolean mMutilyMode; 41 | private int mIconStyle; 42 | private boolean mIsGreater; 43 | private long mFileSize; 44 | 45 | public PathAdapter(List mListData, Context mContext, FileFilter mFileFilter, boolean mMutilyMode, boolean mIsGreater, long mFileSize) { 46 | this.mListData = mListData; 47 | this.mContext = mContext; 48 | this.mFileFilter = mFileFilter; 49 | this.mMutilyMode = mMutilyMode; 50 | this.mIsGreater = mIsGreater; 51 | this.mFileSize = mFileSize; 52 | mCheckedFlags = new boolean[mListData.size()]; 53 | } 54 | 55 | @Override 56 | public PathViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 57 | View view = View.inflate(mContext, R.layout.lfile_listitem, null); 58 | PathViewHolder pathViewHolder = new PathViewHolder(view); 59 | return pathViewHolder; 60 | } 61 | 62 | @Override 63 | public int getItemCount() { 64 | return mListData.size(); 65 | } 66 | 67 | @Override 68 | public void onBindViewHolder(final PathViewHolder holder, final int position) { 69 | final File file = mListData.get(position); 70 | if (file.isFile()) { 71 | updateFileIconStyle(holder.ivType); 72 | holder.tvName.setText(file.getName()); 73 | holder.tvDetail.setText(mContext.getString(R.string.lfile_FileSize) + " " + FileUtils.getReadableFileSize(file.length())); 74 | holder.cbChoose.setVisibility(View.VISIBLE); 75 | } else { 76 | updateFloaderIconStyle(holder.ivType); 77 | holder.tvName.setText(file.getName()); 78 | //文件大小过滤 79 | List files = FileUtils.getFileList(file.getAbsolutePath(), mFileFilter, mIsGreater, mFileSize); 80 | if (files == null) { 81 | holder.tvDetail.setText("0 " + mContext.getString(R.string.lfile_LItem)); 82 | } else { 83 | holder.tvDetail.setText(files.size() + " " + mContext.getString(R.string.lfile_LItem)); 84 | } 85 | holder.cbChoose.setVisibility(View.GONE); 86 | } 87 | if (!mMutilyMode) { 88 | holder.cbChoose.setVisibility(View.GONE); 89 | } 90 | holder.layoutRoot.setOnClickListener(new View.OnClickListener() { 91 | @Override 92 | public void onClick(View v) { 93 | if (file.isFile()) { 94 | holder.cbChoose.setChecked(!holder.cbChoose.isChecked()); 95 | } 96 | onItemClickListener.click(position); 97 | } 98 | }); 99 | holder.cbChoose.setOnClickListener(new View.OnClickListener() { 100 | @Override 101 | public void onClick(View v) { 102 | //同步复选框和外部布局点击的处理 103 | onItemClickListener.click(position); 104 | } 105 | }); 106 | holder.cbChoose.setOnCheckedChangeListener(null);//先设置一次CheckBox的选中监听器,传入参数null 107 | holder.cbChoose.setChecked(mCheckedFlags[position]);//用数组中的值设置CheckBox的选中状态 108 | //再设置一次CheckBox的选中监听器,当CheckBox的选中状态发生改变时,把改变后的状态储存在数组中 109 | holder.cbChoose.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 110 | @Override 111 | public void onCheckedChanged(CompoundButton compoundButton, boolean b) { 112 | mCheckedFlags[position] = b; 113 | } 114 | }); 115 | } 116 | 117 | private void updateFloaderIconStyle(ImageView imageView) { 118 | switch (mIconStyle) { 119 | case Constant.ICON_STYLE_BLUE: 120 | imageView.setBackgroundResource(R.mipmap.lfile_folder_style_blue); 121 | break; 122 | case Constant.ICON_STYLE_GREEN: 123 | imageView.setBackgroundResource(R.mipmap.lfile_folder_style_green); 124 | break; 125 | case Constant.ICON_STYLE_YELLOW: 126 | imageView.setBackgroundResource(R.mipmap.lfile_folder_style_yellow); 127 | break; 128 | } 129 | } 130 | 131 | private void updateFileIconStyle(ImageView imageView) { 132 | switch (mIconStyle) { 133 | case Constant.ICON_STYLE_BLUE: 134 | imageView.setBackgroundResource(R.mipmap.lfile_file_style_blue); 135 | break; 136 | case Constant.ICON_STYLE_GREEN: 137 | imageView.setBackgroundResource(R.mipmap.lfile_file_style_green); 138 | break; 139 | case Constant.ICON_STYLE_YELLOW: 140 | imageView.setBackgroundResource(R.mipmap.lfile_file_style_yellow); 141 | break; 142 | } 143 | } 144 | 145 | /** 146 | * 设置监听器 147 | * 148 | * @param onItemClickListener 149 | */ 150 | public void setOnItemClickListener(OnItemClickListener onItemClickListener) { 151 | this.onItemClickListener = onItemClickListener; 152 | } 153 | 154 | /** 155 | * 设置数据源 156 | * 157 | * @param mListData 158 | */ 159 | public void setmListData(List mListData) { 160 | this.mListData = mListData; 161 | mCheckedFlags = new boolean[mListData.size()]; 162 | } 163 | 164 | public void setmIconStyle(int mIconStyle) { 165 | this.mIconStyle = mIconStyle; 166 | } 167 | 168 | /** 169 | * 设置是否全选 170 | * 171 | * @param isAllSelected 172 | */ 173 | public void updateAllSelelcted(boolean isAllSelected) { 174 | 175 | for (int i = 0; i < mCheckedFlags.length; i++) { 176 | mCheckedFlags[i] = isAllSelected; 177 | } 178 | notifyDataSetChanged(); 179 | } 180 | 181 | class PathViewHolder extends RecyclerView.ViewHolder { 182 | private RelativeLayout layoutRoot; 183 | private ImageView ivType; 184 | private TextView tvName; 185 | private TextView tvDetail; 186 | private CheckBox cbChoose; 187 | 188 | public PathViewHolder(View itemView) { 189 | super(itemView); 190 | ivType = (ImageView) itemView.findViewById(R.id.iv_type); 191 | layoutRoot = (RelativeLayout) itemView.findViewById(R.id.layout_item_root); 192 | tvName = (TextView) itemView.findViewById(R.id.tv_name); 193 | tvDetail = (TextView) itemView.findViewById(R.id.tv_detail); 194 | cbChoose = (CheckBox) itemView.findViewById(R.id.cb_choose); 195 | } 196 | } 197 | } 198 | 199 | 200 | -------------------------------------------------------------------------------- /lfilepickerlibrary/src/main/java/com/leon/lfilepickerlibrary/filter/LFileFilter.java: -------------------------------------------------------------------------------- 1 | package com.leon.lfilepickerlibrary.filter; 2 | 3 | import java.io.File; 4 | import java.io.FileFilter; 5 | 6 | /** 7 | * 作者:Leon 8 | * 时间:2017/3/24 13:43 9 | */ 10 | public class LFileFilter implements FileFilter { 11 | private String[] mTypes; 12 | 13 | public LFileFilter(String[] types) { 14 | this.mTypes = types; 15 | } 16 | 17 | @Override 18 | public boolean accept(File file) { 19 | if (file.isDirectory()) { 20 | return true; 21 | } 22 | if (mTypes != null && mTypes.length > 0) { 23 | for (int i = 0; i < mTypes.length; i++) { 24 | if (file.getName().endsWith(mTypes[i].toLowerCase()) || file.getName().endsWith(mTypes[i].toUpperCase())) { 25 | return true; 26 | } 27 | } 28 | }else { 29 | return true; 30 | } 31 | return false; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /lfilepickerlibrary/src/main/java/com/leon/lfilepickerlibrary/model/ParamEntity.java: -------------------------------------------------------------------------------- 1 | package com.leon.lfilepickerlibrary.model; 2 | 3 | import com.leon.lfilepickerlibrary.R; 4 | 5 | import java.io.Serializable; 6 | 7 | /** 8 | * 作者:Leon 9 | * 时间:2017/3/21 14:50 10 | */ 11 | public class ParamEntity implements Serializable { 12 | private String title; 13 | private String titleColor; 14 | private int titleStyle ; 15 | private int theme ; 16 | private String backgroundColor; 17 | private int backIcon; 18 | private boolean mutilyMode; 19 | private String addText; 20 | private int iconStyle; 21 | private String[] fileTypes; 22 | private String notFoundFiles; 23 | private int maxNum; 24 | private boolean chooseMode = true; 25 | private String path; 26 | private long fileSize; 27 | private boolean isGreater; 28 | 29 | public String getTitle() { 30 | return title; 31 | } 32 | 33 | public void setTitle(String title) { 34 | this.title = title; 35 | } 36 | 37 | @Deprecated 38 | public String getTitleColor() { 39 | return titleColor; 40 | } 41 | 42 | @Deprecated 43 | public void setTitleColor(String titleColor) { 44 | this.titleColor = titleColor; 45 | } 46 | 47 | public int getTheme() { 48 | return theme; 49 | } 50 | 51 | public void setTheme(int theme) { 52 | this.theme = theme; 53 | } 54 | 55 | public int getTitleStyle() { 56 | return titleStyle; 57 | } 58 | 59 | public void setTitleStyle(int titleStyle) { 60 | this.titleStyle = titleStyle; 61 | } 62 | 63 | public String getBackgroundColor() { 64 | return backgroundColor; 65 | } 66 | 67 | public void setBackgroundColor(String backgroundColor) { 68 | this.backgroundColor = backgroundColor; 69 | } 70 | 71 | public boolean isMutilyMode() { 72 | return mutilyMode; 73 | } 74 | 75 | public void setMutilyMode(boolean mutilyMode) { 76 | this.mutilyMode = mutilyMode; 77 | } 78 | 79 | public int getBackIcon() { 80 | return backIcon; 81 | } 82 | 83 | public void setBackIcon(int backIcon) { 84 | this.backIcon = backIcon; 85 | } 86 | 87 | public String getAddText() { 88 | return addText; 89 | } 90 | 91 | public void setAddText(String addText) { 92 | this.addText = addText; 93 | } 94 | 95 | public int getIconStyle() { 96 | return iconStyle; 97 | } 98 | 99 | public void setIconStyle(int iconStyle) { 100 | this.iconStyle = iconStyle; 101 | } 102 | 103 | public String[] getFileTypes() { 104 | return fileTypes; 105 | } 106 | 107 | public void setFileTypes(String[] fileTypes) { 108 | this.fileTypes = fileTypes; 109 | } 110 | 111 | public String getNotFoundFiles() { 112 | return notFoundFiles; 113 | } 114 | 115 | public void setNotFoundFiles(String notFoundFiles) { 116 | this.notFoundFiles = notFoundFiles; 117 | } 118 | 119 | public int getMaxNum() { 120 | return maxNum; 121 | } 122 | 123 | public void setMaxNum(int maxNum) { 124 | this.maxNum = maxNum; 125 | } 126 | 127 | public boolean isChooseMode() { 128 | return chooseMode; 129 | } 130 | 131 | public void setChooseMode(boolean chooseMode) { 132 | this.chooseMode = chooseMode; 133 | } 134 | 135 | public String getPath() { 136 | return path; 137 | } 138 | 139 | public void setPath(String path) { 140 | this.path = path; 141 | } 142 | 143 | public long getFileSize() { 144 | return fileSize; 145 | } 146 | 147 | public void setFileSize(long fileSize) { 148 | this.fileSize = fileSize; 149 | } 150 | 151 | public boolean isGreater() { 152 | return isGreater; 153 | } 154 | 155 | public void setGreater(boolean greater) { 156 | isGreater = greater; 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /lfilepickerlibrary/src/main/java/com/leon/lfilepickerlibrary/ui/LFilePickerActivity.java: -------------------------------------------------------------------------------- 1 | package com.leon.lfilepickerlibrary.ui; 2 | 3 | import android.content.Intent; 4 | import android.graphics.Color; 5 | import android.os.Bundle; 6 | import android.os.Environment; 7 | import android.support.v7.app.AppCompatActivity; 8 | import android.support.v7.widget.LinearLayoutManager; 9 | import android.support.v7.widget.Toolbar; 10 | import android.text.TextUtils; 11 | import android.view.Menu; 12 | import android.view.MenuItem; 13 | import android.view.View; 14 | import android.widget.Button; 15 | import android.widget.TextView; 16 | import android.widget.Toast; 17 | 18 | import com.leon.lfilepickerlibrary.R; 19 | import com.leon.lfilepickerlibrary.adapter.PathAdapter; 20 | import com.leon.lfilepickerlibrary.filter.LFileFilter; 21 | import com.leon.lfilepickerlibrary.model.ParamEntity; 22 | import com.leon.lfilepickerlibrary.utils.Constant; 23 | import com.leon.lfilepickerlibrary.utils.FileUtils; 24 | import com.leon.lfilepickerlibrary.utils.StringUtils; 25 | import com.leon.lfilepickerlibrary.widget.EmptyRecyclerView; 26 | 27 | import java.io.File; 28 | import java.util.ArrayList; 29 | import java.util.List; 30 | 31 | public class LFilePickerActivity extends AppCompatActivity { 32 | 33 | private final String TAG = "FilePickerLeon"; 34 | private EmptyRecyclerView mRecylerView; 35 | private View mEmptyView; 36 | private TextView mTvPath; 37 | private TextView mTvBack; 38 | private Button mBtnAddBook; 39 | private String mPath; 40 | private List mListFiles; 41 | private ArrayList mListNumbers = new ArrayList();//存放选中条目的数据地址 42 | private PathAdapter mPathAdapter; 43 | private Toolbar mToolbar; 44 | private ParamEntity mParamEntity; 45 | private LFileFilter mFilter; 46 | private boolean mIsAllSelected = false; 47 | private Menu mMenu; 48 | 49 | @Override 50 | protected void onCreate(Bundle savedInstanceState) { 51 | mParamEntity = (ParamEntity) getIntent().getExtras().getSerializable("param"); 52 | setTheme(mParamEntity.getTheme()); 53 | super.onCreate(savedInstanceState); 54 | setContentView(R.layout.activity_lfile_picker); 55 | initView(); 56 | setSupportActionBar(mToolbar); 57 | getSupportActionBar().setHomeButtonEnabled(true); 58 | getSupportActionBar().setDisplayHomeAsUpEnabled(true); 59 | initToolbar(); 60 | updateAddButton(); 61 | if (!checkSDState()) { 62 | Toast.makeText(this, R.string.lfile_NotFoundPath, Toast.LENGTH_SHORT).show(); 63 | return; 64 | } 65 | mPath = mParamEntity.getPath(); 66 | if (StringUtils.isEmpty(mPath)) { 67 | //如果没有指定路径,则使用默认路径 68 | mPath = Environment.getExternalStorageDirectory().getAbsolutePath(); 69 | } 70 | mTvPath.setText(mPath); 71 | mFilter = new LFileFilter(mParamEntity.getFileTypes()); 72 | mListFiles = FileUtils.getFileList(mPath, mFilter, mParamEntity.isGreater(), mParamEntity.getFileSize()); 73 | mPathAdapter = new PathAdapter(mListFiles, this, mFilter, mParamEntity.isMutilyMode(), mParamEntity.isGreater(), mParamEntity.getFileSize()); 74 | mRecylerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)); 75 | mPathAdapter.setmIconStyle(mParamEntity.getIconStyle()); 76 | mRecylerView.setAdapter(mPathAdapter); 77 | mRecylerView.setmEmptyView(mEmptyView); 78 | initListener(); 79 | } 80 | 81 | /** 82 | * 更新Toolbar展示 83 | */ 84 | private void initToolbar() { 85 | if (mParamEntity.getTitle() != null) { 86 | mToolbar.setTitle(mParamEntity.getTitle()); 87 | } 88 | if (mParamEntity.getTitleStyle() != 0) { 89 | mToolbar.setTitleTextAppearance(this, mParamEntity.getTitleStyle()); 90 | } 91 | if (mParamEntity.getTitleColor() != null) { 92 | mToolbar.setTitleTextColor(Color.parseColor(mParamEntity.getTitleColor())); //设置标题颜色 93 | } 94 | if (mParamEntity.getBackgroundColor() != null) { 95 | mToolbar.setBackgroundColor(Color.parseColor(mParamEntity.getBackgroundColor())); 96 | } 97 | switch (mParamEntity.getBackIcon()) { 98 | case Constant.BACKICON_STYLEONE: 99 | mToolbar.setNavigationIcon(R.mipmap.lfile_back1); 100 | break; 101 | case Constant.BACKICON_STYLETWO: 102 | mToolbar.setNavigationIcon(R.mipmap.lfile_back2); 103 | break; 104 | case Constant.BACKICON_STYLETHREE: 105 | //默认风格 106 | break; 107 | } 108 | mToolbar.setNavigationOnClickListener(new View.OnClickListener() { 109 | @Override 110 | public void onClick(View v) { 111 | finish(); 112 | } 113 | }); 114 | } 115 | 116 | private void updateAddButton() { 117 | if (!mParamEntity.isMutilyMode()) { 118 | mBtnAddBook.setVisibility(View.GONE); 119 | } 120 | if (!mParamEntity.isChooseMode()) { 121 | mBtnAddBook.setVisibility(View.VISIBLE); 122 | mBtnAddBook.setText(getString(R.string.lfile_OK)); 123 | //文件夹模式默认为单选模式 124 | mParamEntity.setMutilyMode(false); 125 | } 126 | } 127 | 128 | /** 129 | * 添加点击事件处理 130 | */ 131 | private void initListener() { 132 | // 返回目录上一级 133 | mTvBack.setOnClickListener(new View.OnClickListener() { 134 | @Override 135 | public void onClick(View v) { 136 | String tempPath = new File(mPath).getParent(); 137 | if (tempPath == null) { 138 | return; 139 | } 140 | mPath = tempPath; 141 | mListFiles = FileUtils.getFileList(mPath, mFilter, mParamEntity.isGreater(), mParamEntity.getFileSize()); 142 | mPathAdapter.setmListData(mListFiles); 143 | mPathAdapter.updateAllSelelcted(false); 144 | mIsAllSelected = false; 145 | updateMenuTitle(); 146 | mBtnAddBook.setText(getString(R.string.lfile_Selected)); 147 | mRecylerView.scrollToPosition(0); 148 | setShowPath(mPath); 149 | //清除添加集合中数据 150 | mListNumbers.clear(); 151 | if (mParamEntity.getAddText() != null) { 152 | mBtnAddBook.setText(mParamEntity.getAddText()); 153 | } else { 154 | mBtnAddBook.setText(R.string.lfile_Selected); 155 | } 156 | } 157 | }); 158 | mPathAdapter.setOnItemClickListener(new PathAdapter.OnItemClickListener() { 159 | @Override 160 | public void click(int position) { 161 | if (mParamEntity.isMutilyMode()) { 162 | if (mListFiles.get(position).isDirectory()) { 163 | //如果当前是目录,则进入继续查看目录 164 | chekInDirectory(position); 165 | mPathAdapter.updateAllSelelcted(false); 166 | mIsAllSelected = false; 167 | updateMenuTitle(); 168 | mBtnAddBook.setText(getString(R.string.lfile_Selected)); 169 | } else { 170 | //如果已经选择则取消,否则添加进来 171 | if (mListNumbers.contains(mListFiles.get(position).getAbsolutePath())) { 172 | mListNumbers.remove(mListFiles.get(position).getAbsolutePath()); 173 | } else { 174 | mListNumbers.add(mListFiles.get(position).getAbsolutePath()); 175 | } 176 | if (mParamEntity.getAddText() != null) { 177 | mBtnAddBook.setText(mParamEntity.getAddText() + "( " + mListNumbers.size() + " )"); 178 | } else { 179 | mBtnAddBook.setText(getString(R.string.lfile_Selected) + "( " + mListNumbers.size() + " )"); 180 | } 181 | //先判断是否达到最大数量,如果数量达到上限提示,否则继续添加 182 | if (mParamEntity.getMaxNum() > 0 && mListNumbers.size() > mParamEntity.getMaxNum()) { 183 | Toast.makeText(LFilePickerActivity.this, R.string.lfile_OutSize, Toast.LENGTH_SHORT).show(); 184 | return; 185 | } 186 | } 187 | } else { 188 | //单选模式直接返回 189 | if (mListFiles.get(position).isDirectory()) { 190 | chekInDirectory(position); 191 | return; 192 | } 193 | if (mParamEntity.isChooseMode()) { 194 | //选择文件模式,需要添加文件路径,否则为文件夹模式,直接返回当前路径 195 | mListNumbers.add(mListFiles.get(position).getAbsolutePath()); 196 | chooseDone(); 197 | } else { 198 | Toast.makeText(LFilePickerActivity.this, R.string.lfile_ChooseTip, Toast.LENGTH_SHORT).show(); 199 | } 200 | } 201 | 202 | } 203 | }); 204 | 205 | mBtnAddBook.setOnClickListener(new View.OnClickListener() { 206 | @Override 207 | public void onClick(View v) { 208 | if (mParamEntity.isChooseMode() && mListNumbers.size() < 1) { 209 | String info = mParamEntity.getNotFoundFiles(); 210 | if (TextUtils.isEmpty(info)) { 211 | Toast.makeText(LFilePickerActivity.this, R.string.lfile_NotFoundBooks, Toast.LENGTH_SHORT).show(); 212 | } else { 213 | Toast.makeText(LFilePickerActivity.this, info, Toast.LENGTH_SHORT).show(); 214 | } 215 | } else { 216 | //返回 217 | chooseDone(); 218 | } 219 | } 220 | }); 221 | } 222 | 223 | 224 | /** 225 | * 点击进入目录 226 | * 227 | * @param position 228 | */ 229 | private void chekInDirectory(int position) { 230 | mPath = mListFiles.get(position).getAbsolutePath(); 231 | setShowPath(mPath); 232 | //更新数据源 233 | mListFiles = FileUtils.getFileList(mPath, mFilter, mParamEntity.isGreater(), mParamEntity.getFileSize()); 234 | mPathAdapter.setmListData(mListFiles); 235 | mPathAdapter.notifyDataSetChanged(); 236 | mRecylerView.scrollToPosition(0); 237 | } 238 | 239 | /** 240 | * 完成提交 241 | */ 242 | private void chooseDone() { 243 | //判断是否数量符合要求 244 | if (mParamEntity.isChooseMode()) { 245 | if (mParamEntity.getMaxNum() > 0 && mListNumbers.size() > mParamEntity.getMaxNum()) { 246 | Toast.makeText(LFilePickerActivity.this, R.string.lfile_OutSize, Toast.LENGTH_SHORT).show(); 247 | return; 248 | } 249 | } 250 | Intent intent = new Intent(); 251 | intent.putStringArrayListExtra("paths", mListNumbers); 252 | intent.putExtra("path", mTvPath.getText().toString().trim()); 253 | setResult(RESULT_OK, intent); 254 | this.finish(); 255 | } 256 | 257 | /** 258 | * 初始化控件 259 | */ 260 | private void initView() { 261 | mRecylerView = (EmptyRecyclerView) findViewById(R.id.recylerview); 262 | mTvPath = (TextView) findViewById(R.id.tv_path); 263 | mTvBack = (TextView) findViewById(R.id.tv_back); 264 | mBtnAddBook = (Button) findViewById(R.id.btn_addbook); 265 | mEmptyView = findViewById(R.id.empty_view); 266 | mToolbar = (Toolbar) findViewById(R.id.toolbar); 267 | if (mParamEntity.getAddText() != null) { 268 | mBtnAddBook.setText(mParamEntity.getAddText()); 269 | } 270 | } 271 | 272 | /** 273 | * 检测SD卡是否可用 274 | */ 275 | private boolean checkSDState() { 276 | return Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED); 277 | } 278 | 279 | /** 280 | * 显示顶部地址 281 | * 282 | * @param path 283 | */ 284 | private void setShowPath(String path) { 285 | mTvPath.setText(path); 286 | } 287 | 288 | @Override 289 | public boolean onCreateOptionsMenu(Menu menu) { 290 | getMenuInflater().inflate(R.menu.menu_main_toolbar, menu); 291 | this.mMenu = menu; 292 | updateOptionsMenu(menu); 293 | return true; 294 | } 295 | 296 | /** 297 | * 更新选项菜单展示,如果是单选模式,不显示全选操作 298 | * 299 | * @param menu 300 | */ 301 | private void updateOptionsMenu(Menu menu) { 302 | mMenu.findItem(R.id.action_selecteall_cancel).setVisible(mParamEntity.isMutilyMode()); 303 | } 304 | 305 | @Override 306 | public boolean onOptionsItemSelected(MenuItem item) { 307 | if (item.getItemId() == R.id.action_selecteall_cancel) { 308 | //将当前目录下所有文件选中或者取消 309 | mPathAdapter.updateAllSelelcted(!mIsAllSelected); 310 | mIsAllSelected = !mIsAllSelected; 311 | if (mIsAllSelected) { 312 | for (File mListFile : mListFiles) { 313 | //不包含再添加,避免重复添加 314 | if (!mListFile.isDirectory() && !mListNumbers.contains(mListFile.getAbsolutePath())) { 315 | mListNumbers.add(mListFile.getAbsolutePath()); 316 | } 317 | if (mParamEntity.getAddText() != null) { 318 | mBtnAddBook.setText(mParamEntity.getAddText() + "( " + mListNumbers.size() + " )"); 319 | } else { 320 | mBtnAddBook.setText(getString(R.string.lfile_Selected) + "( " + mListNumbers.size() + " )"); 321 | } 322 | } 323 | } else { 324 | mListNumbers.clear(); 325 | mBtnAddBook.setText(getString(R.string.lfile_Selected)); 326 | } 327 | updateMenuTitle(); 328 | } 329 | return true; 330 | } 331 | 332 | /** 333 | * 更新选项菜单文字 334 | */ 335 | public void updateMenuTitle() { 336 | 337 | if (mIsAllSelected) { 338 | mMenu.getItem(0).setTitle(getString(R.string.lfile_Cancel)); 339 | } else { 340 | mMenu.getItem(0).setTitle(getString(R.string.lfile_SelectAll)); 341 | } 342 | } 343 | 344 | } 345 | -------------------------------------------------------------------------------- /lfilepickerlibrary/src/main/java/com/leon/lfilepickerlibrary/utils/CloseUtils.java: -------------------------------------------------------------------------------- 1 | package com.leon.lfilepickerlibrary.utils; 2 | 3 | import java.io.Closeable; 4 | import java.io.IOException; 5 | 6 | /** 7 | *
 8 |  *     author: Blankj
 9 |  *     blog  : http://blankj.com
10 |  *     time  : 2016/10/9
11 |  *     desc  : 关闭相关工具类
12 |  * 
13 | */ 14 | public class CloseUtils { 15 | 16 | private CloseUtils() { 17 | throw new UnsupportedOperationException("u can't instantiate me..."); 18 | } 19 | 20 | /** 21 | * 关闭IO 22 | * 23 | * @param closeables closeables 24 | */ 25 | public static void closeIO(Closeable... closeables) { 26 | if (closeables == null) return; 27 | for (Closeable closeable : closeables) { 28 | if (closeable != null) { 29 | try { 30 | closeable.close(); 31 | } catch (IOException e) { 32 | e.printStackTrace(); 33 | } 34 | } 35 | } 36 | } 37 | 38 | /** 39 | * 安静关闭IO 40 | * 41 | * @param closeables closeables 42 | */ 43 | public static void closeIOQuietly(Closeable... closeables) { 44 | if (closeables == null) return; 45 | for (Closeable closeable : closeables) { 46 | if (closeable != null) { 47 | try { 48 | closeable.close(); 49 | } catch (IOException ignored) { 50 | } 51 | } 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /lfilepickerlibrary/src/main/java/com/leon/lfilepickerlibrary/utils/CompositeFilter.java: -------------------------------------------------------------------------------- 1 | package com.leon.lfilepickerlibrary.utils; 2 | 3 | import java.io.File; 4 | import java.io.FileFilter; 5 | import java.io.Serializable; 6 | import java.util.ArrayList; 7 | 8 | /** 9 | * Created by Dimorinny on 31.05.16. 10 | */ 11 | public class CompositeFilter implements FileFilter, Serializable { 12 | 13 | private ArrayList mFilters; 14 | 15 | public CompositeFilter(ArrayList filters) { 16 | mFilters = filters; 17 | } 18 | 19 | @Override 20 | public boolean accept(File f) { 21 | for (FileFilter filter : mFilters) { 22 | if (!filter.accept(f)) { 23 | return false; 24 | } 25 | } 26 | 27 | return true; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /lfilepickerlibrary/src/main/java/com/leon/lfilepickerlibrary/utils/Constant.java: -------------------------------------------------------------------------------- 1 | package com.leon.lfilepickerlibrary.utils; 2 | 3 | /** 4 | * 作者:Leon 5 | * 时间:2017/3/21 15:06 6 | * 7 | */ 8 | public class Constant { 9 | //返回图标风格 10 | public static final int BACKICON_STYLEONE = 0; 11 | public static final int BACKICON_STYLETWO = 1; 12 | public static final int BACKICON_STYLETHREE = 2; 13 | //图标风格 14 | public static final int ICON_STYLE_YELLOW = 0; 15 | public static final int ICON_STYLE_BLUE = 1; 16 | public static final int ICON_STYLE_GREEN = 2; 17 | 18 | public static String RESULT_INFO = "paths"; 19 | } 20 | -------------------------------------------------------------------------------- /lfilepickerlibrary/src/main/java/com/leon/lfilepickerlibrary/utils/FileComparator.java: -------------------------------------------------------------------------------- 1 | package com.leon.lfilepickerlibrary.utils; 2 | 3 | import java.io.File; 4 | import java.util.Comparator; 5 | 6 | /** 7 | * Created by Dimorinny on 24.10.15. 8 | */ 9 | public class FileComparator implements Comparator { 10 | @Override 11 | public int compare(File f1, File f2) { 12 | if(f1 == f2) { 13 | return 0; 14 | } 15 | if(f1.isDirectory() && f2.isFile()) { 16 | // Show directories above files 17 | return -1; 18 | } 19 | if(f1.isFile() && f2.isDirectory()) { 20 | // Show files below directories 21 | return 1; 22 | } 23 | // Sort the directories alphabetically 24 | return f1.getName().compareToIgnoreCase(f2.getName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /lfilepickerlibrary/src/main/java/com/leon/lfilepickerlibrary/utils/FileUtils.java: -------------------------------------------------------------------------------- 1 | package com.leon.lfilepickerlibrary.utils; 2 | 3 | import android.util.Log; 4 | 5 | import java.io.File; 6 | import java.io.FileFilter; 7 | import java.text.DecimalFormat; 8 | import java.util.ArrayList; 9 | import java.util.Arrays; 10 | import java.util.Collections; 11 | import java.util.Iterator; 12 | import java.util.List; 13 | 14 | /** 15 | * Created by Dimorinny on 24.10.15. 16 | */ 17 | public class FileUtils { 18 | public static List getFileListByDirPath(String path, FileFilter filter) { 19 | File directory = new File(path); 20 | File[] files = directory.listFiles(filter); 21 | List result = new ArrayList<>(); 22 | if (files == null) { 23 | return new ArrayList<>(); 24 | } 25 | 26 | for (int i = 0; i < files.length; i++) { 27 | result.add(files[i]); 28 | } 29 | Collections.sort(result, new FileComparator()); 30 | return result; 31 | } 32 | 33 | public static String cutLastSegmentOfPath(String path) { 34 | return path.substring(0, path.lastIndexOf("/")); 35 | } 36 | 37 | public static String getReadableFileSize(long size) { 38 | if (size <= 0) return "0"; 39 | final String[] units = new String[]{"B", "KB", "MB", "GB", "TB"}; 40 | int digitGroups = (int) (Math.log10(size) / Math.log10(1024)); 41 | return new DecimalFormat("#").format(size / Math.pow(1024, digitGroups)) + " " + units[digitGroups]; 42 | } 43 | 44 | /** 45 | * 获取文件长度 46 | * 47 | * @param file 文件 48 | * @return 文件长度 49 | */ 50 | public static long getFileLength(final File file) { 51 | if (!isFile(file)) return -1; 52 | return file.length(); 53 | } 54 | 55 | /** 56 | * 判断是否是文件 57 | * 58 | * @param file 文件 59 | * @return {@code true}: 是
{@code false}: 否 60 | */ 61 | public static boolean isFile(final File file) { 62 | return file != null && file.exists() && file.isFile(); 63 | } 64 | 65 | /** 66 | * 根据地址获取当前地址下的所有目录和文件,并且排序,同时过滤掉不符合大小要求的文件 67 | * 68 | * @param path 69 | * @return List 70 | */ 71 | public static List getFileList(String path, FileFilter filter, boolean isGreater, long targetSize) { 72 | List list = FileUtils.getFileListByDirPath(path, filter); 73 | //进行过滤文件大小 74 | Iterator iterator = list.iterator(); 75 | while (iterator.hasNext()) { 76 | File f = (File) iterator.next(); 77 | if (f.isFile()) { 78 | //获取当前文件大小 79 | long size = FileUtils.getFileLength(f); 80 | if (isGreater) { 81 | //当前想要留下大于指定大小的文件,所以过滤掉小于指定大小的文件 82 | if (size < targetSize) { 83 | iterator.remove(); 84 | } 85 | } else { 86 | //当前想要留下小于指定大小的文件,所以过滤掉大于指定大小的文件 87 | if (size > targetSize) { 88 | iterator.remove(); 89 | } 90 | } 91 | } 92 | } 93 | return list; 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /lfilepickerlibrary/src/main/java/com/leon/lfilepickerlibrary/utils/MemoryConstant.java: -------------------------------------------------------------------------------- 1 | package com.leon.lfilepickerlibrary.utils; 2 | 3 | import android.support.annotation.IntDef; 4 | 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | 8 | /** 9 | *
10 |  *     author: Blankj
11 |  *     blog  : http://blankj.com
12 |  *     time  : 2017/03/13
13 |  *     desc  : 存储相关常量
14 |  * 
15 | */ 16 | public class MemoryConstant { 17 | 18 | /** 19 | * Byte与Byte的倍数 20 | */ 21 | public static final int BYTE = 1; 22 | /** 23 | * KB与Byte的倍数 24 | */ 25 | public static final int KB = 1024; 26 | /** 27 | * MB与Byte的倍数 28 | */ 29 | public static final int MB = 1048576; 30 | /** 31 | * GB与Byte的倍数 32 | */ 33 | public static final int GB = 1073741824; 34 | 35 | @IntDef({BYTE, KB, MB, GB}) 36 | @Retention(RetentionPolicy.SOURCE) 37 | public @interface Unit { 38 | } 39 | } -------------------------------------------------------------------------------- /lfilepickerlibrary/src/main/java/com/leon/lfilepickerlibrary/utils/StringUtils.java: -------------------------------------------------------------------------------- 1 | package com.leon.lfilepickerlibrary.utils; 2 | 3 | /** 4 | *
  5 |  *     author: Blankj
  6 |  *     blog  : http://blankj.com
  7 |  *     time  : 2016/8/16
  8 |  *     desc  : 字符串相关工具类
  9 |  * 
10 | */ 11 | public class StringUtils { 12 | 13 | private StringUtils() { 14 | throw new UnsupportedOperationException("u can't instantiate me..."); 15 | } 16 | 17 | /** 18 | * 判断字符串是否为null或长度为0 19 | * 20 | * @param s 待校验字符串 21 | * @return {@code true}: 空
{@code false}: 不为空 22 | */ 23 | public static boolean isEmpty(CharSequence s) { 24 | return s == null || s.length() == 0; 25 | } 26 | 27 | /** 28 | * 判断字符串是否为null或全为空格 29 | * 30 | * @param s 待校验字符串 31 | * @return {@code true}: null或全空格
{@code false}: 不为null且不全空格 32 | */ 33 | public static boolean isSpace(String s) { 34 | return (s == null || s.trim().length() == 0); 35 | } 36 | 37 | /** 38 | * 判断两字符串是否相等 39 | * 40 | * @param a 待校验字符串a 41 | * @param b 待校验字符串b 42 | * @return {@code true}: 相等
{@code false}: 不相等 43 | */ 44 | public static boolean equals(CharSequence a, CharSequence b) { 45 | if (a == b) return true; 46 | int length; 47 | if (a != null && b != null && (length = a.length()) == b.length()) { 48 | if (a instanceof String && b instanceof String) { 49 | return a.equals(b); 50 | } else { 51 | for (int i = 0; i < length; i++) { 52 | if (a.charAt(i) != b.charAt(i)) return false; 53 | } 54 | return true; 55 | } 56 | } 57 | return false; 58 | } 59 | 60 | /** 61 | * 判断两字符串忽略大小写是否相等 62 | * 63 | * @param a 待校验字符串a 64 | * @param b 待校验字符串b 65 | * @return {@code true}: 相等
{@code false}: 不相等 66 | */ 67 | public static boolean equalsIgnoreCase(String a, String b) { 68 | return (a == b) || (b != null) && (a.length() == b.length()) && a.regionMatches(true, 0, b, 0, b.length()); 69 | } 70 | 71 | /** 72 | * null转为长度为0的字符串 73 | * 74 | * @param s 待转字符串 75 | * @return s为null转为长度为0字符串,否则不改变 76 | */ 77 | public static String null2Length0(String s) { 78 | return s == null ? "" : s; 79 | } 80 | 81 | /** 82 | * 返回字符串长度 83 | * 84 | * @param s 字符串 85 | * @return null返回0,其他返回自身长度 86 | */ 87 | public static int length(CharSequence s) { 88 | return s == null ? 0 : s.length(); 89 | } 90 | 91 | /** 92 | * 首字母大写 93 | * 94 | * @param s 待转字符串 95 | * @return 首字母大写字符串 96 | */ 97 | public static String upperFirstLetter(String s) { 98 | if (isEmpty(s) || !Character.isLowerCase(s.charAt(0))) return s; 99 | return String.valueOf((char) (s.charAt(0) - 32)) + s.substring(1); 100 | } 101 | 102 | /** 103 | * 首字母小写 104 | * 105 | * @param s 待转字符串 106 | * @return 首字母小写字符串 107 | */ 108 | public static String lowerFirstLetter(String s) { 109 | if (isEmpty(s) || !Character.isUpperCase(s.charAt(0))) return s; 110 | return String.valueOf((char) (s.charAt(0) + 32)) + s.substring(1); 111 | } 112 | 113 | /** 114 | * 反转字符串 115 | * 116 | * @param s 待反转字符串 117 | * @return 反转字符串 118 | */ 119 | public static String reverse(String s) { 120 | int len = length(s); 121 | if (len <= 1) return s; 122 | int mid = len >> 1; 123 | char[] chars = s.toCharArray(); 124 | char c; 125 | for (int i = 0; i < mid; ++i) { 126 | c = chars[i]; 127 | chars[i] = chars[len - i - 1]; 128 | chars[len - i - 1] = c; 129 | } 130 | return new String(chars); 131 | } 132 | 133 | /** 134 | * 转化为半角字符 135 | * 136 | * @param s 待转字符串 137 | * @return 半角字符串 138 | */ 139 | public static String toDBC(String s) { 140 | if (isEmpty(s)) return s; 141 | char[] chars = s.toCharArray(); 142 | for (int i = 0, len = chars.length; i < len; i++) { 143 | if (chars[i] == 12288) { 144 | chars[i] = ' '; 145 | } else if (65281 <= chars[i] && chars[i] <= 65374) { 146 | chars[i] = (char) (chars[i] - 65248); 147 | } else { 148 | chars[i] = chars[i]; 149 | } 150 | } 151 | return new String(chars); 152 | } 153 | 154 | /** 155 | * 转化为全角字符 156 | * 157 | * @param s 待转字符串 158 | * @return 全角字符串 159 | */ 160 | public static String toSBC(String s) { 161 | if (isEmpty(s)) return s; 162 | char[] chars = s.toCharArray(); 163 | for (int i = 0, len = chars.length; i < len; i++) { 164 | if (chars[i] == ' ') { 165 | chars[i] = (char) 12288; 166 | } else if (33 <= chars[i] && chars[i] <= 126) { 167 | chars[i] = (char) (chars[i] + 65248); 168 | } else { 169 | chars[i] = chars[i]; 170 | } 171 | } 172 | return new String(chars); 173 | } 174 | } -------------------------------------------------------------------------------- /lfilepickerlibrary/src/main/java/com/leon/lfilepickerlibrary/widget/EmptyRecyclerView.java: -------------------------------------------------------------------------------- 1 | package com.leon.lfilepickerlibrary.widget; 2 | 3 | import android.content.Context; 4 | import android.support.annotation.Nullable; 5 | import android.support.v7.widget.RecyclerView; 6 | import android.util.AttributeSet; 7 | import android.view.View; 8 | 9 | /** 10 | * 作者:Leon 11 | * 时间:2017/3/17 13:44 12 | */ 13 | public class EmptyRecyclerView extends RecyclerView { 14 | private View mEmptyView; 15 | 16 | public EmptyRecyclerView(Context context) { 17 | super(context); 18 | } 19 | 20 | public EmptyRecyclerView(Context context, @Nullable AttributeSet attrs) { 21 | super(context, attrs); 22 | } 23 | 24 | public EmptyRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) { 25 | super(context, attrs, defStyle); 26 | } 27 | 28 | /** 29 | * 根据数据源判断是否显示空白view 30 | */ 31 | private void checkIfEmpty() { 32 | if (mEmptyView != null || getAdapter() != null) { 33 | mEmptyView.setVisibility(getAdapter().getItemCount() > 0 ? GONE : VISIBLE); 34 | } 35 | } 36 | 37 | public void setmEmptyView(View mEmptyView) { 38 | this.mEmptyView = mEmptyView; 39 | checkIfEmpty(); 40 | } 41 | 42 | @Override 43 | public void setAdapter(Adapter adapter) { 44 | Adapter adapterOld = getAdapter(); 45 | if (adapterOld != null) { 46 | adapterOld.unregisterAdapterDataObserver(observer); 47 | } 48 | super.setAdapter(adapter); 49 | if (adapter != null) { 50 | adapter.registerAdapterDataObserver(observer); 51 | } 52 | } 53 | 54 | AdapterDataObserver observer = new AdapterDataObserver() { 55 | @Override 56 | public void onChanged() { 57 | super.onChanged(); 58 | checkIfEmpty(); 59 | } 60 | }; 61 | } 62 | -------------------------------------------------------------------------------- /lfilepickerlibrary/src/main/res/drawable-v21/lfile_back_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 8 | -------------------------------------------------------------------------------- /lfilepickerlibrary/src/main/res/drawable-v21/lfile_btn_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 8 | -------------------------------------------------------------------------------- /lfilepickerlibrary/src/main/res/drawable/back_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /lfilepickerlibrary/src/main/res/drawable/btn_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /lfilepickerlibrary/src/main/res/drawable/item_bg_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /lfilepickerlibrary/src/main/res/drawable/lfile_back_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /lfilepickerlibrary/src/main/res/drawable/lfile_btn_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /lfilepickerlibrary/src/main/res/layout/activity_lfile_picker.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 17 | 25 | 26 | 36 | 37 | 50 | 51 | 52 |