rxAndroid 和ActionMode實現(xiàn)簡易文件瀏覽器

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ù)的綁定就省略了
最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容