ActionMode簡介
Android 3.0以前,我們處理列表的長按事件經(jīng)常使用Context Menu,Android3.0以后,我們有了新的選擇:ActionMode。
Android開發(fā)者應該都熟悉Context Menu了,Context Menu是懸浮在操作項之上的視圖,ActionMode是臨時占據(jù)了ActionBar的位置。
ActionMode使用步驟
實現(xiàn)ActionMode.Callbak接口,并處理其生命周期方法即可
1.public boolean onCreateActionMode(ActionMode mode, Menu menu)
2.public boolean onPrepareActionMode(ActionMode mode, Menu menu)
3.public boolean onActionItemClicked(ActionMode mode, MenuItem item)
4.public void onDestroyActionMode(ActionMode mode)
重寫ActionMode
package com.example.simpleexplore;
import android.app.Activity;
import android.support.v7.view.ActionMode;
import android.view.Menu;
import android.view.MenuItem;
import android.view.Window;
/**
* Created by Administrator on 2017/8/5 0005.
*/
public class ActionModeCallback implements ActionMode.Callback{
private Activity activity;
private Window window;
private ActionListener mActionListener;
private ActionMode actionMode;
private boolean isShowing = true;
public ActionModeCallback(Activity activity,ActionListener listener){
this.activity = activity;
this.window = activity.getWindow();
mActionListener = listener;
}
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
actionMode = mode;
mode.getMenuInflater().inflate(R.menu.menu_item_top,menu);
return true;
}
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
}
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
if(item.getItemId() == R.id.menu_item_done){
if(mActionListener != null){
mActionListener.onFinishAction();
}
}else if(item.getItemId() == R.id.menu_item_delete){
if(mActionListener != null){
mActionListener.onDeleteAction();
}
}
mode.finish();
return false;
}
@Override
public void onDestroyActionMode(ActionMode mode) {
isShowing = false;
if(mActionListener != null){
mActionListener.onDismissAction();
}
}
/**
* 更新title
* @param count
*/
public void updateTitleSelectItemCount(int count){
if(actionMode != null){
actionMode.setTitle(count + (count > 1?"items":"item") + "selected");
}
}
/**
* 退出actionMode
*/
public void dismiss(){
if(actionMode != null){
actionMode.finish();
}
}
/**
* ActionmMode 是否開啟
*/
public boolean isShowing(){
return isShowing;
}
/**
* 設置ActionMode的開啟
* @param showing
*/
public void setShowing(boolean showing){
isShowing = showing;
}
/**
* actionMode的監(jiān)聽者
*/
public interface ActionListener {
void onFinishAction();
void onDismissAction();
void onDeleteAction();
}
}
```
###定義文件model
```
public class FileWraper {
/**
* 文件
*/
public File file;
/**
* 是否選中
*/
public boolean isSelected = false;
public FileWraper(){
}
public FileWraper(File file){
this.file = file;
}
public FileWraper(File file,boolean isSelected){
this.file = file;
this.isSelected = isSelected;
}
}
```
###定義堆棧
存儲每次瀏覽時訪問節(jié)點的記錄
```
public class FileTreeStack {
//棧頂節(jié)點
private Node mTopNode;
//棧內(nèi)元素個數(shù)
private int mSize;
//入棧
public void push(FileShotSnap shotSnap){
Node node = new Node();
node.shotSnap = shotSnap;
node.next = mTopNode;
mTopNode = node;//尾插法
mSize++;
}
//出棧
public FileShotSnap pop(){
if(mTopNode == null) return null;
FileShotSnap shotSnap = mTopNode.shotSnap;
mTopNode = mTopNode.next;
mSize--;
return shotSnap;
}
/**
* 返回堆棧大小
* @return
*/
public int size(){
return mSize;
}
//訪問節(jié)點
class Node {
FileShotSnap shotSnap;
Node next;//指向下一個節(jié)點
}
public static class FileShotSnap {
//母文件夾
public File parent;
//此文件夾下的文件
public List files;
//y上的滑動距離
public int ScrollY;
}
}
```
###MainActvity
```
public class FileExploreActivity extends BaseActivity {
@BindView(R.id.recycler_view)
RecyclerView recyclerView;
private int position;
//根目錄
private File rootFile = Environment.getExternalStorage();
//文件訪問棧
private FileTreeStack mFileStack;
private ActionModeCallback mCallback;
//當前狀態(tài)下的母文件夾
File mCurrentFileParent;
//當前所有文件
List mCurrentFiles;
//選中的文件列表
List mSelectedFiles = new ArrayList<>();
private FileAdapter adapter;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_file_explore);
ButterKnife.bind(this);
initView();
}
//回退
@Override
public void onBackPressed() {
if(mFileStack.size() == 0){
super.onBackPressed();
}else {
restoreTreeStack(mFileStack.pop());
}
}
private void initView() {
adapter = new FileAdapter(this,null);
adapter.setOnClickListener(new ListAdapter.OnItemClickListener() {
@Override
public void onClick(View itemView, int position) {
//獲取選中文件
FileWraper item = adapter.getItem(position);
if(item.file.isDirectory()){
//如果是在選擇狀態(tài)
if(isInModeAction()){
//選中或取消文件
updateSelectFiles(item,position);
}else {
//進入文件夾 首先堆棧
storeTreeStack();
//加載文件
loadFiles(item.file);
//刷新標題
updateTitle();
}
}
}
});
adapter.setOnItemLongClickListener(new ListAdapter.OnItemLongClickListener() {
@Override
public void onLongClick(View itemView, int position) {
FileWraper item = adapter.getItem(position);
//長按進入選則文件狀態(tài)
if(item.file.isDirectory()){
if(mCallback == null || !mCallback.isShowing()){
startActionMode();
}
//選中或取消文件
updateSelectFiles(item,position);
}
}
});
recyclerView.setAdapter(adapter);
//加載音樂
loadFiles(rootFile);
}
private void startActionMode() {
if(mCallback == null){
mCallback = new ActionModeCallback(this, new ActionModeCallback.ActionListener() {
@Override
public void onFinishAction() {
//選中
Toast.makeText(FileExploreActivity.this, "選中所有", Toast.LENGTH_SHORT).show();
if(mSelectedFiles.size() > 0){
//操作
} else {
mCallback.dismiss();
}
}
@Override
public void onDismissAction() {
//取消
Toast.makeText(FileExploreActivity.this, "取消續(xù)重", Toast.LENGTH_SHORT).show();
clearSelections();
}
@Override
public void onDeleteAction() {
//刪除
Toast.makeText(FileExploreActivity.this, "刪除選中文件", Toast.LENGTH_SHORT).show();
}
});
}
startSupportActionMode(mCallback);//開啟ActionMode ActionBar被替代,進入選擇文件狀態(tài)
mCallback.setShowing(true);
}
//清楚當前所有選中文件
private void clearSelections() {
boolean needClear = mSelectedFiles.size() > 0;
mSelectedFiles.clear();
if(needClear){
adapter.clearSelections();
adapter.notifyDataSetChanged();
}
}
//更新選中或取消
private void updateSelectFiles(FileWraper fileWraper,int position) {
if(fileWraper.file.isFile()) return;
//更新文件選中狀態(tài)
fileWraper.isSelected = !fileWraper.isSelected;
//添加或取消選中
if(fileWraper.isSelected){
mSelectedFiles.add(fileWraper.file);
}else {
if(mSelectedFiles.indexOf(fileWraper.file) != -1){
mSelectedFiles.remove(fileWraper.file);
}
}
//更新UI
adapter.notifyItemChanged(position);
//更新選中UI
mCallback.updateTitleSelectItemCount(mSelectedFiles.size());
}
/**
* 更新標題
*/
private void updateTitle() {
getSupportActionBar().setTitle(mCurrentFileParent.getName());
}
/**
* 存儲節(jié)點
*/
private void storeTreeStack() {
//把當前節(jié)點加入樹棧中
FileTreeStack.FileShotSnap shotSnap = new FileTreeStack.FileShotSnap();
shotSnap.parent = mCurrentFileParent;
shotSnap.files = mCurrentFiles;
mFileStack.push(shotSnap);
}
/**
* 取出節(jié)點
* @param top
*/
private void restoreTreeStack(FileTreeStack.FileShotSnap top) {
mCurrentFileParent = top.parent;
mCurrentFiles = top.files;
int scrollOffsetY = top.ScrollY;
adapter.setDate(mCurrentFiles);
adapter.notifyDataSetChanged();
recyclerView.scrollTo(0,scrollOffsetY);
}
/**
* 判斷是否在選擇模式下
* @return
*/
private boolean isInModeAction() {
//如果第一個條件不符合 就直接返回 不會看第二個
return mCallback != null && mCallback.isShowing();
}
/**
* 加載文件 并更新UI
*/
private void loadFiles(File parent) {
//rxAndroid 加載文件
Subscription subscription = Observable.just(parent)
.flatMap(new Func1>>() {
@Override
public Observable> call(File parent) {
List files = Arrays.asList(parent.listFiles(SystemFileFilter.DEFAULT_INSTANCE));
Collections.sort(files, new Comparator() {
@Override
public int compare(File f1, File f2) {
if (f1.isDirectory() && f2.isFile()) {
return -1;
}
if (f2.isDirectory() && f1.isFile()) {
return 1;
}
return f1.getName().compareToIgnoreCase(f2.getName());
}
});
// 創(chuàng)建文件列表
List fileWrappers = new ArrayList<>(files.size());
for (File file : files) {
fileWrappers.add(new FileWrapper(file));
}
return Observable.just(fileWrappers);
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable throwable) {
Log.e(TAG, "onError: ", throwable);
}
@Override
public void onNext(List files) {
mCurrentFiles = files;
onFileLoaded(parent);
}
});
addSubscription(subscription);
}
private void onFileLoaded(File parent) {
mCurrentFileParent = parent;
//刷新數(shù)據(jù)
adapter.setDate(mCurrentFiles);
adapter.notifyDataSetChanged();
//進入文件夾的時候滑動到第一個位置就可以
recyclerView.scrollTo(0,0);
}
}
```
適配器及數(shù)據(jù)的綁定就省略了