介面無小事(一): RecyclerView+CardView瞭解一下
介面無小事(二): 讓RecyclerView展示更多不同檢視
介面無小事(三):用RecyclerView + Toolbar做個檔案選擇器
目錄
- 前言
- 最終效果演示
- 佈局檔案
- RecyclerView介面卡
- Toolbar的使用
- 填充RecyclerView條目
- 懸浮按鈕
- 最後
前言
在之前兩期也是說了很多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" />
複製程式碼

然後使用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要被巨硬收購, 瑟瑟發抖.