[Android]聊聊ActionMode

最近一段時間都沒有更新文章,趁工作之余,更新一篇。

今天介紹一個很常見效果也最容易被忽略的彈出框: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 ...
        
    }
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,578評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,701評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,691評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,974評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,694評論 6 413
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,026評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,015評論 3 450
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,193評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,719評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,442評論 3 360
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,668評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,151評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,846評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,255評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,592評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,394評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,635評論 2 380

推薦閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,771評論 25 708
  • 發現 關注 消息 iOS 第三方庫、插件、知名博客總結 作者大灰狼的小綿羊哥哥關注 2017.06.26 09:4...
    肇東周閱讀 12,180評論 4 61
  • 如果說我的成長是一杯咖啡,那么我祝福惠寶寶的成長是一杯清水。咖啡已經成型,無論味道還是顏色,而清水卻有萬般可能,對...
    繪一繪生活閱讀 263評論 0 2
  • 功名利祿利名功, 空虛盡時盡虛空。 濁酒伴壺伴酒濁, 東籬下來下籬東。
    離之_905d閱讀 294評論 0 2
  • 今天在某平臺看到一位閨蜜的貼子,心緒久久不能平靜。貼子的開頭是這樣寫的,“大家好,我是第一次來這里留言,希望...
    流年淺夢閱讀 260評論 1 1