Android 文件选择器 DFileSelector

源码地址:https://github.com/mengzhinan/FileSelector

前段时间准备给朋友做一个手机小工具,需要用到选择文件并读取里面的内容。

这个读扩展卡选择文件的功能呢,其实也不难,就是个 RecyclerView 和 Adapter 而已。但是感觉自己有点懒,想找找开源的项目用用。

网上搜索了下,还真有一个叫 LFilePicker 的项目,地址为 https://github.com/leonHua/LFilePicker

非常好的项目,很优秀,感谢首创的分享精神。坐着考虑的很全面细致,使用起来很简单。有兴趣的麻友自己去看看。

然而,有强迫症的我,不甘示弱啊。自己阅读了作者的项目,吸收了其优秀数点,再根据自己的思路,也写了一个同样功能的开源小项目。

一、先来看看效果图吧(抱歉,静态图)

1、需要申请读扩展卡权限

2、单选模式,选择后直接返回到上一个页面,在回调函数中返回选择的文件路径

3、多选模式,勾选一定数量的文件后,点击底部的确定,返回到上一个也难,回调函数中获取选中的文件路径集合

以上就是大概的默认效果图。

什么?非常像小米手机的文件管理器界面?对,我就是打开小米手机的文件管理器界面,然后自己码的砖。

抄袭?不存在的,我是忠实的米粉,看了它一眼而已,界面效果还不错。

二、为什么还要自己造轮子?

1、首先,作为一个程序员,有充足的时间和心理准备,为什么不自己动手试试呢?你怕多学到什么了吗?又不是赶项目。

2、作者的项目确实很优秀。但是个人感觉部分功能包装的无余地了。比喻 title 、statusBar 部分,有些需求可能不需要这部分,或者需要考虑到沉浸式状态栏,岂不是很尴尬。

3、文件类型图标,扩展性不好。图标样式只提供了几种选择,而且貌似文件扩展类型的图标没有个性化处理。

4、当然,首创作者的项目也有很多优点的,其中之一:提供了 maven 引入的便捷方式。等等。

三、我的轮子有哪些优点?

1、和谐的界面效果,米粉们有福了。 

2、支持单选、多选模式。

3、处理局部结构和多选框样式不能改变外,其他的任何位置都可以自定义属性值。比喻:宽、高、字体大小、字体颜色、文件、图标资源等等,即你可设置 RecyclerView 层面和 Item 层面任意处的样式。

4、兼容你的感受,提供多种打开方式。比喻:以 Activity 的方式打开、在你的页面直接写布局和 Java 代码。

5、可自定义文件排序比较器、文件图标提供器、文件过滤器等重要扩展功能。

6、可以通过设置回调、监听广播或在 onActivityResult() 方法的方式获取到选中的文件信息,非常灵活。

7、也支持中、英文两种语言。

四、怎么使用呢?

1、直接使用代码库中的默认 Activity 启动文件选择器,包含 onActivityResult() 和 Receiver 两种接收返回数据方法,自己辨别。内部已经处理了动态权限。

/**
 * 使用默认的Activity启动选择器
 */
public class Demo1Activity extends AppCompatActivity implements View.OnClickListener {
    private TextView selectFIle;
    public static final String TAG = "MainActivityTest";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_demo1);
        selectFIle = findViewById(R.id.textview_select_file);
        selectFIle.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        if (v == null) {
            return;
        }
        int id = v.getId();
        if (id == R.id.textview_select_file) {
            DefaultSelectorActivity.startActivity(this);//包含广播
//            DefaultSelectorActivity.startActivityForResult(this);
        }
    }

//    @Override
//    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
//        super.onActivityResult(requestCode, resultCode, data);
//        if (resultCode == Activity.RESULT_OK && requestCode == DefaultSelectorActivity.FILE_SELECT_REQUEST_CODE) {
//            printData(DefaultSelectorActivity.getDataFromIntent(data));
//        }
//    }

    private BroadcastReceiver receiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (context == null || intent == null) {
                return;
            }
            if (DefaultSelectorActivity.FILE_SELECT_ACTION.equals(intent.getAction())) {
                printData(DefaultSelectorActivity.getDataFromIntent(intent));
                Demo1Activity.this.finish();
            }
        }
    };


    private boolean isRegister;
    private IntentFilter intentFilter = new IntentFilter(DefaultSelectorActivity.FILE_SELECT_ACTION);

    @Override
    protected void onResume() {
        super.onResume();
        if (!isRegister) {
            registerReceiver(receiver, intentFilter);
            isRegister = true;
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (isRegister) {
            unregisterReceiver(receiver);
            isRegister = false;
        }
    }

    private void printData(ArrayList<String> list) {
        if (FileSelectorUtils.isEmpty(list)) {
            return;
        }
        int size = list.size();
        Log.v(TAG, "获取到数据-开始 size = " + size);
        StringBuffer stringBuffer = new StringBuffer("选中的文件:\r\n");
        for (int i = 0; i < size; i++) {
            Log.v(TAG, (i + 1) + " = " + list.get(i));
            stringBuffer.append(list.get(i));
            stringBuffer.append("\r\n");
        }
        Toast.makeText(this, stringBuffer.toString(), Toast.LENGTH_SHORT).show();
        Log.v(TAG, "获取到数据-结束");
    }
}

2、直接使用文件选择器的自定义控件,不包含状态栏和标题栏。自己实现动态权限和深度定制 UI。

R.layout.activity_demo3.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".Demo3Activity">

    <com.duke.dfileselector.widget.FileSelectorLayout
        android:id="@+id/file_select_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</android.support.constraint.ConstraintLayout>

Demo3Activity.java

/**
 * 直接使用自定义view启动选择器
 */
public class Demo3Activity extends BasePermissionActivity {
    private FileSelectorLayout fileSelectorLayout;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_demo3);
        fileSelectorLayout = findViewById(R.id.file_select_layout);
    }

    @Override
    protected void onPermissionSuccess() {
        FileSelector.with(fileSelectorLayout).listen(new FileSelector.OnFileSelectListener() {
            @Override
            public void onSelected(ArrayList<String> list) {
                Toast.makeText(Demo3Activity.this, "选中文件个数: size = " + (list == null ? 0 : list.size()), Toast.LENGTH_SHORT).show();
                Demo3Activity.this.finish();
            }
        }).setup();
    }
}

说明:

1、BasePermissionActivity.java 是我提供的处理动态权限基类,包含在代码库中。你只需关心 onPermissionSuccess() 权限申请成功方法即可。

2、上例中,你可以通过 FileSelector 类的静态方法定制 UI。

五、FileSelector API 简单介绍( 有点过分 )


FileSelector.with(fileSelectorLayout)
                .listen(onFileSelectListener) // 设置文件选中回调
                .setItemParameter(ItemParameter.with(fileSelectorLayout.getContext())// 设置列表 item 的各种属性样式
                                .setTitleTextSize(R.dimen.sp_20)          // 设置 item 文件名字体大小
                                .setTitleTextColor(Color.RED)             // 设置 item 文件名字体颜色
                                .setTitleTextBold(true)                   // 设置 item 文件名字体粗细
                                .setImageWidth(R.dimen.dp_50)             // 设置 item 文件扩展类型图片宽度
                                .setImageHeight(R.dimen.dp_50)            // 设置 item 文件扩展类型图片高度
                                .setImageMarginRight(R.dimen.dp_50)       // 设置 item 文件扩展类型图片右边间距
                                .setCountTextColor(Color.RED)             // 设置 item 文件个数字体颜色
                                .setCountTextSize(R.dimen.sp_20)          // 设置 item 文件个数字体大小
                                .setCountTextBold(true)                   // 设置 item 文件个数字体粗细
                                .setDateTextSize(R.dimen.sp_20)           // 设置 item 文件日期字体大小
                                .setDateTextColor(Color.RED)              // 设置 item 文件日期字体颜色
                                .setDateTextBold(true)                    // 设置 item 文件日期字体粗细
                                .setLayoutBackgroundColor(Color.RED)      // 设置 item 背景颜色
                                .setLayoutPadding(R.dimen.dp_1, R.dimen.dp_1, R.dimen.dp_1, R.dimen.dp_1) // 设置 item 边距
                                .setSplitLineColor(Color.RED)             // 设置 item 的文件个数与日期之间分割线的颜色
                                .setSplitLineHeight(R.dimen.dp_10)        // 设置 item 的文件个数与日期之间分割线的高度
                                .setSplitLineWidth(R.dimen.dp_10)         // 设置 item 的文件个数与日期之间分割线的宽度
                                .setSplitLineMarginLeft(R.dimen.dp_50)    // 设置 item 的文件个数与日期之间分割线的左间距
                                .setSplitLineMarginRight(R.dimen.dp_50)   // 设置 item 的文件个数与日期之间分割线的右间距
                )
                .setMultiSelectionModel(true)                             // 设置是否为多选模式
                .setMultiModelMaxSize(3)                                  // 设置多选模式时最多可选中文件的个数
                .setMultiModelToast(true, "最多只能选择3个文件")          // 设置多选模式选择数量达到上限值时是否需要 Toast 提示
                .setFileSizeProvide(FileSizeProvide fileSizeProvide)      // 设置文件个数处的自定义文本样式
                .setFileIconProvide(FileIconProvide fileIconProvide)      // 设置文件扩展类型图片自定义提供器
                .setFileDateProvide(FileDateProvide fileDateProvide)      // 设置文件日期格式化样式自定义提供器
                .setFileFilter(FileFilter fileFilter)                     // 设置自动以文件顾虑器
                .setFileOrderProvide(FileOrderProvide fileOrderProvide)   // 设置文件排序比较器
                .setHeadTopLineVisibility(View.VISIBLE)                   // 设置列表顶部路径栏上边的横线
                .setHeadTopLineColor(Color.RED)                           // 设置列表顶部路径栏上边横线颜色
                .setHeadTopLineHeight(R.dimen.dp_30)                      // 设置列表顶部路径栏上边横线高度
                .setHeadTopLineHeightDP(30)                               // 同上
                .setHeadTopLineHeightPX(30)                               // 同上
                .setHeadTopLineMargin(R.dimen.dp_10, R.dimen.dp_10,R.dimen.dp_10,R.dimen.dp_10) // 设置列表顶部路径栏上边横线边距
                .setHeadTopLineMarginDP(10,10,10,10)                      // 同上
                .setHeadTopLineMarginPX(10,10,10,10)                      // 同上
                .setHeadBottomLineVisibility(View.VISIBLE)                // 设置类表顶部路径栏下边的横线
                .setHeadBottomLineColor(@ColorInt int color)              // 设置类表顶部路径栏下边横线的颜色
                .setHeadBottomLineHeight(@DimenRes int resId)             // 设置类表顶部路径栏下边横线的高度
                .setHeadBottomLineHeightDP(float dpHeight)                // 同上
                .setHeadBottomLineHeightPX(float pxHeight)                // 同上
                .setHeadBottomLineMargin(@DimenRes int leftDimenRes, @DimenRes int topDimenRes, @DimenRes int rightDimenRes, @DimenRes int bottomDimenRes)
                .setHeadBottomLineMarginDP(float leftDP, float topDP, float rightDP, float bottomDP)
                .setHeadBottomLineMarginPX(float leftPX, float topPX, float rightPX, float bottomPX)
                .setHeadRootHeight(R.dimen.dp_40)                         // 设置列表顶部路栏高度
                .setHeadRootHeightDP(40)                                  // 同上
                .setHeadRootHeightPX(120)                                 // 同上
                .setHeadRootPadding(R.dimen.dp_20,R.dimen.dp_1,R.dimen.dp_30,R.dimen.dp_1)        // 设置列表顶部路栏内容边距
                .setHeadRootPaddingDP(float leftDP, float topDP, float rightDP, float bottomDP)   // 同上
                .setHeadRootPaddingPX(float leftPX, float topPX, float rightPX, float bottomPX)   // 同上
                .setHeadRootBackgroundColor(Color.RED)                    // 设置列表顶部路栏背景颜色
                .setHeadRootBackgroundResource(@DrawableRes int resId)    // 设置列表顶部路栏背景资源
                .setHeadLeftTextSize(R.dimen.sp_20)                       // 设置列表顶部路栏左边路径字体大小
                .setHeadLeftTextSizePX(60)                                // 同上
                .setHeadLeftTextSizeSP(20)                                // 同上
                .setHeadLeftTextColor(Color.RED)                          // 设置列表顶部路栏左边路径字体颜色
                .setHeadLeftTextColor(ColorStateList colors)              // 同上
                .setHeadLeftTextBold(true)                                // 设置列表顶部路栏左边路径字体粗细
                .setHeadLeftTextEllipsize(TextUtils.TruncateAt.MARQUEE)   // 设置列表顶部路栏左边路径字体省略模式
                .setHeadRightImage(Drawable leftDrawable)                 // 设置列表顶部路栏右边返回按钮左边的图片资源
                .setHeadRightImageDP(Drawable leftDrawable, float widthDP, float heightDP) // 同上
                .setHeadRightImagePX(Drawable leftDrawable, float widthPX, float heightPX) // 同上
                .setHeadRightText(@StringRes int resId)                   // 设置列表顶部路栏右边返回按钮的文本
                .setHeadRightText("上一级")                               // 同上
                .setHeadRightTextSize(@DimenRes int resId)                // 设置列表顶部路栏右边返回按钮的字体大小
                .setHeadRightTextSizePX(float px)                         // 同上
                .setHeadRightTextSizeSP(20)                               // 同上
                .setHeadRightTextColor(Color.RED)                         // 设置列表顶部路栏右边返回按钮的字体颜色
                .setHeadRightTextColor(ColorStateList colors)             // 同上
                .setHeadRightTextBold(true)                               // 设置列表顶部路栏右边返回按钮的字体粗细
                .setHeadRightTextBackgroundColor(Color.RED)               // 设置列表顶部路栏右边返回按钮的背景
                .setHeadRightTextBackgroundResource(@DrawableRes int resId)// 同上
                .setRecyclerViewLineDecoration(RecyclerView.ItemDecoration itemDecoration) // 设置列表的 item 分割线提供器
                .setRecyclerViewLineColorHeight(Color.RED, R.dimen.dp_1, R.dimen.dp_5)     // 同上
                .setRecyclerViewLineColorHeightDP(@ColorInt int color, float heightDP, float marginDP) // 同上
                .setRecyclerViewLineColorHeightPX(@ColorInt int color, float heightPX, float marginPX) // 同上
                .setRecyclerViewBackgroundColor(Color.GRAY)                   // 设置列表背景颜色
                .setRecyclerViewBackgroundResource(@DrawableRes int resId)    // 设置列表背景资源
                .setEmptyText(@StringRes int resId)                           // 设置无数据界面的提示文本
                .setEmptyText("无数据")                                       // 同上
                .setEmptyTextColor(Color.RED)                                 // 设置无数据界面的提示文本的颜色
                .setEmptyTextColor(ColorStateList colors)                     // 同上
                .setEmptyTextSize(@DimenRes int resId)                        // 设置无数据界面的提示文本字体大小
                .setEmptyTextSizePX(float px)                                 // 同上
                .setEmptyTextSizeSP(float sp)                                 // 同上
                .setEmptyTopImage(@DrawableRes int topDrawableResId)          // 设置无数据界面的提示文本的顶部图片资源
                .setEmptyTopImage(Drawable topDrawable)                       // 同上
                .setEmptyTopImage(@DrawableRes int topDrawableResId, @DimenRes int widthResId, @DimenRes int heightResId)
                .setEmptyTopImageDP(Drawable topDrawable, float widthDP, float heightDP)
                .setEmptyTopImagePX(Drawable topDrawable, float widthPX, float heightPX)
                .setSubmitTextViewHeight(@DimenRes int resId)                 // 多选模式,设置确定按钮控件的高度
                .setSubmitTextViewHeightDP(float dpHeight)                    // 同上
                .setSubmitTextViewHeightPX(float pxHeight)                    // 同上
                .setSubmitText(@StringRes int resId)                          // 多选模式,设置确定按钮的文本
                .setSubmitText("ok")                                          // 同上
                .setSubmitTextColor(@ColorInt int color)                      // 多选模式,设置确定按钮的字体颜色
                .setSubmitTextColor(ColorStateList colors)                    // 同上
                .setSubmitTextSize(@DimenRes int resId)                       // 多选模式,设置确定按钮的字体大小
                .setSubmitTextSizePX(float px)                                // 同上
                .setSubmitTextSizeSP(float sp)                                // 同上
                .setSubmitTextBold(boolean isBold)                            // 多选模式,设置确定按钮的字体粗细
                .setSubmitViewBackgroundColor(Color.RED)                      // 多选模式,设置确定按钮的背景颜色
                .setSubmitViewBackgroundResource(@DrawableRes int resId)      // 多选模式,设置确定按钮的背景资源
                .setDefaultFile(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)) // 添加设置默认路径方法
                .setup();                                                     // 生效设置,最后必须调用,否则 UI 界面无数据。


重点就是这些了,有兴趣的可以下载试用。

源码地址:https://github.com/mengzhinan/FileSelector

猜你喜欢

转载自blog.csdn.net/fesdgasdgasdg/article/details/83720720