界面无小事(三):用RecyclerView + Toolbar做个文件选择器

793 阅读4分钟

界面无小事(一): RecyclerView+CardView了解一下

界面无小事(二): 让RecyclerView展示更多不同视图

界面无小事(三):用RecyclerView + Toolbar做个文件选择器

界面无小事(四):来写个滚动选择器吧!

界面无小事(五):自定义TextView

界面无小事(六):来做个好看得侧拉菜单!


目录

  • 前言
  • 最终效果演示
  • 布局文件
  • RecyclerView适配器
  • Toolbar的使用
  • 填充RecyclerView条目
  • 悬浮按钮
  • 最后

前言

github传送门

在之前两期也是说了很多RecyclerView的使用, 这期打算来个实操性质的. 用RecyclerView制作一个文件管理器, 并且可以进行文件的多选, 应该是蛮实用的.


最终效果展示

最终效果展示


布局文件

还是先从最简单的布局文件开始看. 可以看到, 三个字符串和一个图标. 图标依据是文件夹或者文件进行显示, 当然了, 之后会做得更细, 例如依据文件类型进行图标变换, mp3就显示为音乐, mp4就是显示视频. 上方字符串是文件或者文件夹名称. 下方字符串的话, 见下面的展示图, 依据类型进行显示:

布局文件

文件夹

文件


RecyclerView适配器

具体的使用在之前文章里面也细说过了. 这里来看两个关键函数. 我们的填充内容主要是当前目录下全部的files, 存放在ArrayList当中. 每当用户展开新的一层, 就会调用refreshData函数进行刷新. 如果是单选或者是多选, 就会调用refreshSelect函数进行对应的处理. 整体也比较简单, 不多赘述.

public void refreshData(ArrayList<File> files) {
    mFiles = files;
    this.notifyDataSetChanged();
}

public int refreshSelect(int pos) {
    if (pos < 0) {
        if (pos == -1) {
            // 全不选
            mSelectList.clear();
        } else if (pos == -2) {
            // 全选
            for (int i = 0; i < mFiles.size(); i++) {
                if (mFiles.get(i).isFile() && !mSelectList.contains((Integer) i)) {
                    mSelectList.add((Integer) i);
                }
            }
        }
    } else {
        // 单选
        if (!mSelectList.contains((Integer) pos)) {
            mSelectList.add((Integer) pos);
        } else {
            mSelectList.remove((Integer) pos);
        }
    }
    this.notifyDataSetChanged();

    return mSelectList.size();
}

Toolbar的使用

Toolbar是个好东西. 你可以看看官方文档. 反正我自从会用了之后, 几乎没有不用的时候. Toolbar使用细节的文章就太多了, 我也不多说了. 但是app:layout_scrollFlags="scroll|enterAlways|snap"这行还是很重要的, 作用就是让Toolbar在上拉RecyclerView的时候隐藏, 下拉的时候显示. 来张效果图:

<android.support.v7.widget.Toolbar
    android:id="@+id/toolbar"
    android:layout_width="match_parent"
    android:layout_height="?attr/actionBarSize"
    android:background="?attr/colorPrimary"
    app:layout_scrollFlags="scroll|enterAlways|snap"
    app:popupTheme="@style/AppTheme.PopupOverlay" />

Toolbar隐藏和显示

然后使用setTitle函数可以修改Toolbar中标题内容, 关于变化内容的字符串使用可以看我之前的文章.

getSupportActionBar().setTitle(
        String.format(getResources().getString(
                R.string.selected_str), mSelectCount));

如果你要在Toolbar上添加按钮:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/all"
        android:icon="@drawable/all"
        android:orderInCategory="100"
        android:title="@string/all"
        app:showAsAction="ifRoom" />
</menu>
@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}

添加对应按钮的点击监听的话:

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case android.R.id.home:
            break;
        case R.id.all:
            break;
    }
    return true;
}

android.R.id.home是系统自带的一个返回按钮, 和ios的返回类似, 你懂的~. 当然了, 一般是不显示出来的, 你需要如下代码:

ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
    actionBar.setDisplayHomeAsUpEnabled(true);
}

填充RecyclerView条目

既然要使用RecyclerView, 条目填充就很重要了. 思路就是使用Stack进行当前路径存储, 后续每点击一个文件夹就添加一层, 每返回一层, 就弹出一个.

// 获取sdcard目录
mSdcardPath = Environment.getExternalStorageDirectory().toString();

mSelectPath = new ArrayList<>();

mCurPathStack = new Stack<>();

mCurFileList = new ArrayList<>();

File[] files = Environment.getExternalStorageDirectory().listFiles();
if (files != null) {
    for (File f : files) {
        mCurFileList.add(f);
    }
}

mCurPathStack.push(mSdcardPath);

具体细节肯定要查看下源码的, 这里看到mCurPathStack就是处理路径的. mCurFileList用来存储当前展开文件夹的内容. mSelectPath用来存储勾选的文件.

mFMAdapter.setOnItemClickListener(new FMAdapter.OnItemClickListener() {
    @Override
    public void onItemClick(View view, int position) {
        final File file = mCurFileList.get(position);
        if (file.isDirectory()) {
            // 是文件夹
            mCurPathStack.push("/" + file.getName());

            // 根据路径刷新数据
            refreshData(getCurPath());
        } else {
            // 是文件
            mSelectCount = mFMAdapter.refreshSelect(position);
            getSupportActionBar()
                    .setTitle(String.format(getResources()
                            .getString(R.string.selected_str), mSelectCount));

            // 将选中的文件加入文件路径数组
            if (!mSelectPath.contains(file.getAbsolutePath())) {
                mSelectPath.add(file.getAbsolutePath());
            } else {
                mSelectPath.remove(file.getAbsolutePath());
            }
        }
    }

    @Override
    public void onItemLongClick(View view, int position) {

    }
});

然后对每一个条目添加点击事件, 长按事件的话, 大家可以按照自己的喜欢处理, 这里不多写了. 主要是单击事件. 如果是点击文件夹, 就将点击文件夹加入栈, 然后刷新视图. 如果是文件, 就是单选文件, 需要将位置传给适配器函数refreshSelect, 这个之前也说过了. 一个比较重要的就是, 在当前的mSelectPath中需要进行确认, 如果已经存在就删除这个选择, 如果不存在, 就选择这个文件, 这个逻辑也是很好理解的.


悬浮按钮

这个也是非常常用的一个视图类. 如果你点击了悬浮按钮, 就会弹出确认窗口, 关于弹窗, 可以查看我之前的文章. 这里就上一张效果图了.

悬浮按钮

点击演示


最后

好了, 就写到这里了, 喜欢记得点赞或者关注我哦, 有意见或者建议评论区见哦. 然后点击这里查看源码, 听说github要被巨硬收购, 瑟瑟发抖.