[Android]聊聊ActionMode

来源:互联网 发布:女人依靠男人 知乎 编辑:程序博客网 时间:2024/06/06 03:25

最近一段时间都没有更新文章,趁工作之余,更新一篇。

今天介绍一个很常见效果也最容易被忽略的弹出框:ActionMode。主要是ActionMode使用和自己使用过程中遇到的一些问题,相对还是比较简单的。

1、ActionMode的基本使用
2、使用ActionMode遇到的一些问题

ActionMode

1、ActionMode的基本使用

主要分两步:
1、实现ActionMode.Callback接口
2、调用startActionMode或者startSupportActionMode

1、实现ActionMode.Callback接口

ActionMode.Callback

对于ActionMode.Callback,我们需要实现其四个方法:

new ActionMode.Callback() {            //Called when action mode is first created.            // The menu supplied will be used to generate action buttons for the action mode            //当ActionMode第一次被创建的时候调用            //可在这里初始化menu            @Override            public boolean onCreateActionMode(ActionMode mode, Menu menu) {            MenuInflater inflater = mode.getMenuInflater();            inflater.inflate(R.menu.menu, menu);            menu.findItem(R.id.action_edit).setIcon(R.drawable.ic_launcher);                return true;//返回true表示action mode会被创建  false if entering this mode should be aborted.            }            //            @Override            public boolean onPrepareActionMode(ActionMode mode, Menu menu) {                return false;            }            //当ActionMode被点击时调用            @Override            public boolean onActionItemClicked(ActionMode mode, MenuItem item) {                 switch (item.getItemId()) {                    case R.id.action_edit:                            rename();                        return true;                    }                return false;            }            //Called when an action mode is about to be exited and destroyed.            //当ActionMode退出销毁时调用            @Override            public void onDestroyActionMode(ActionMode mode) {            }        };

2、调用startActionMode或者startSupportActionMode开启弹出框

ActionMode mActionMode = = startSupportActionMode(actionModeCallback)

可以为ActionMode设置属性:mActionMode.setTitlemActionMode.setSubtitle

2、使用ActionMode遇到的坑

坑一:ActionMode把Toolbar压下去了

ActionMode Toolbar

在theme加入配置:

<item name="windowActionModeOverlay">true</item>
<item name="android:windowActionModeOverlay">true</item>

坑二:修改ActionMode背景

在theme加入配置:

<item name="android:actionModeBackground">@color/colorPrimary</item>
<item name="actionModeBackground">@color/colorPrimary</item>

坑三:屏蔽掉WebView的ActionMode用自己的选择复制
通过js与webView互调来实现文本复制
stackoverflow链接:http://stackoverflow.com/questions/6058843/android-how-to-select-texts-from-webview

public class MyCustomWebView extends WebView{    private Context context;    // override all other constructor to avoid crash    public MyCustomWebView(Context context) {        super(context);        this.context = context;        WebSettings webviewSettings = getSettings();        webviewSettings.setJavaScriptEnabled(true);        // add JavaScript interface for copy        addJavascriptInterface(new WebAppInterface(context), "JSInterface");    }    // setting custom action bar    private ActionMode mActionMode;    private ActionMode.Callback mSelectActionModeCallback;    private GestureDetector mDetector;    // this will over ride the default action bar on long press    @Override    public ActionMode startActionMode(ActionMode.Callback callback) {        ViewParent parent = getParent();        if (parent == null) {            return null;        }        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {            String name = callback.getClass().toString();            if (name.contains("SelectActionModeCallback")) {                mSelectActionModeCallback = callback;                mDetector = new GestureDetector(context,                        new CustomGestureListener());            }        }        CustomActionModeCallback mActionModeCallback = new CustomActionModeCallback();        return parent.startActionModeForChild(this, mActionModeCallback);    }    private class CustomActionModeCallback implements ActionMode.Callback {        @Override        public boolean onCreateActionMode(ActionMode mode, Menu menu) {            mActionMode = mode;            MenuInflater inflater = mode.getMenuInflater();            inflater.inflate(R.menu.menu, menu);            return true;        }        @Override        public boolean onPrepareActionMode(ActionMode mode, Menu menu) {            return false;        }        @Override        public boolean onActionItemClicked(ActionMode mode, MenuItem item) {            switch (item.getItemId()) {                case R.id.copy:                    getSelectedData();                    mode.finish();                    return true;                case R.id.share:                    mode.finish();                    return true;                default:                    mode.finish();                    return false;            }        }        @Override        public void onDestroyActionMode(ActionMode mode) {            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {                clearFocus();            }else{                if (mSelectActionModeCallback != null) {                    mSelectActionModeCallback.onDestroyActionMode(mode);                }                mActionMode = null;            }        }    }    private void getSelectedData(){        String js= "(function getSelectedText() {"+                "var txt;"+                "if (window.getSelection) {"+                "txt = window.getSelection().toString();"+                "} else if (window.document.getSelection) {"+                "txt = window.document.getSelection().toString();"+                "} else if (window.document.selection) {"+                "txt = window.document.selection.createRange().text;"+                "}"+                "JSInterface.getText(txt);"+                "})()";        // calling the js function        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {            evaluateJavascript("javascript:"+js, null);        }else{            loadUrl("javascript:"+js);        }    }    private class CustomGestureListener extends GestureDetector.SimpleOnGestureListener {        @Override        public boolean onSingleTapUp(MotionEvent e) {            if (mActionMode != null) {                mActionMode.finish();                return true;            }            return false;        }    }    @Override    public boolean onTouchEvent(MotionEvent event) {        // Send the event to our gesture detector        // If it is implemented, there will be a return value        if(mDetector !=null)            mDetector.onTouchEvent(event);        // If the detected gesture is unimplemented, send it to the superclass        return super.onTouchEvent(event);    }    public class WebAppInterface {        Context mContext;        WebAppInterface(Context c) {            mContext = c;        }        @JavascriptInterface        public void getText(String text) {            // put selected text into clipdata            ClipboardManager clipboard = (ClipboardManager)                    mContext.getSystemService(Context.CLIPBOARD_SERVICE);            ClipData clip = ClipData.newPlainText("simple text",text);            clipboard.setPrimaryClip(clip);            // gives the toast for selected text            Toast.makeText(mContext, text, Toast.LENGTH_SHORT).show();        }    }}

menu.xml:

<?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/copy"        android:icon="@android:drawable/ic_dialog_email"        app:showAsAction="always"        android:title="copy">    </item>    <item        android:id="@+id/share"        android:icon="@android:drawable/ic_dialog_alert"        app:showAsAction="always"        android:title="share">    </item>    </menu>

坑四:ActionMode显示时状态栏闪动,表现为变黑之后恢复正常
onDestroyActionMode方法加入如下代码:

    @Override    public final void onDestroyActionMode(ActionMode mode) {        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {            new Handler().postDelayed(new Runnable() {                @TargetApi(Build.VERSION_CODES.LOLLIPOP)                @Override                public void run() {                    try {                        mActivity.getWindow().setStatusBarColor(mActivity.getResources().getColor(android.R.color.transparent));                    }                    catch(Exception e)                    {                        e.printStackTrace();                    }                }            }, 400);        }        //TODO ...    }
0 1
原创粉丝点击