ActionMode简介
Android 3.0以前,我们处理列表的长按事件经常使用Context Menu,Android3.0以后,我们有了新的选择:ActionMode。
Android开发者应该都熟悉Context Menu了,Context Menu是悬浮在操作项之上的视图,ActionMode是临时占据了ActionBar的位置。
ActionMode使用步骤
实现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的监听者
*/
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;
}
}
```
###定义堆栈
存储每次浏览时访问节点的记录
```
public class FileTreeStack {
//栈顶节点
private Node mTopNode;
//栈内元素个数
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;
}
//访问节点
class Node {
FileShotSnap shotSnap;
Node next;//指向下一个节点
}
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;
//当前状态下的母文件夹
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()){
//如果是在选择状态
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);
//长按进入选则文件状态
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, "取消续重", Toast.LENGTH_SHORT).show();
clearSelections();
}
@Override
public void onDeleteAction() {
//删除
Toast.makeText(FileExploreActivity.this, "删除选中文件", Toast.LENGTH_SHORT).show();
}
});
}
startSupportActionMode(mCallback);//开启ActionMode ActionBar被替代,进入选择文件状态
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;
//更新文件选中状态
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());
}
/**
* 存储节点
*/
private void storeTreeStack() {
//把当前节点加入树栈中
FileTreeStack.FileShotSnap shotSnap = new FileTreeStack.FileShotSnap();
shotSnap.parent = mCurrentFileParent;
shotSnap.files = mCurrentFiles;
mFileStack.push(shotSnap);
}
/**
* 取出节点
* @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());
}
});
// 创建文件列表
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;
//刷新数据
adapter.setDate(mCurrentFiles);
adapter.notifyDataSetChanged();
//进入文件夹的时候滑动到第一个位置就可以
recyclerView.scrollTo(0,0);
}
}
```
适配器及数据的绑定就省略了