rxAndroid 和ActionMode实现简易文件浏览器

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);

    }

}
```

适配器及数据的绑定就省略了

你可能感兴趣的:(rxAndroid 和ActionMode实现简易文件浏览器)