Android修改6.0系统文本选择菜单

因为我身患流行性绝症(拖延症),不知不觉中博客已经有半年没更新了 ( ⊙ o ⊙ )。

正好最近在写文本选择菜单的功能,就整理出了一篇文章,算是我与该死的拖延症展开的殊死搏斗吧。

本文主要写了在Android6.0+版本上,修改EditText、TextView的文本选择菜单内容和为其他APP提供自定义文本操作这两个功能。

1.修改EditText和TextView的文本选择菜单内容

Android官方控件中,EditText中的文字默认长按呼出文本选择菜单,而TextView需要设置android:textIsSelectable="true"。

我们修改文本选择菜单内容,只需要为TextView或者EditText设置setCustomSelectionActionModeCallback()方法,并且在方法里实现ActionMode.Callback()或ActionMode.Callback2()接口。

ActionMode.Callback()和ActionMode.Callback2()接口的主要内容相同,只是Callback2中多了一个onGetContentRect()方法,重写可以改变弹出菜单的位置。另外,Callback2需要判断sdk23及以上版本,Callback()不用,但是在6.0以下系统中实际是无效的。

我们先在res下的menu文件夹里新建一个菜单文件,我把它命名为selection_action_menu.xml,内容如下

    <?xml version="1.0" encoding="utf-8"?>
    <menu
 xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/Informal22"
        android:title="自定义22" />
    <item
        android:id="@+id/Informal33"
        android:title="自定义33" />
 </menu>

然后我们完成文本选择菜单的修改

    ActionMode.Callback2 textSelectionActionModeCallback;
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
        textSelectionActionModeCallback = new ActionMode.Callback2() {
            @Override
            public boolean onCreateActionMode(ActionMode actionMode, Menu menu) {
                MenuInflater menuInflater = actionMode.getMenuInflater();
                menuInflater.inflate(R.menu.selection_action_menu,menu);
                return true;//返回false则不会显示弹窗
            }

            @Override
            public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) {
                return false;
            }

            @Override
            public boolean onActionItemClicked(ActionMode actionMode, MenuItem menuItem) {
                //根据item的ID处理点击事件
                switch (menuItem.getItemId()){
                    case R.id.Informal22:
                        Toast.makeText(MainActivity.this, "点击的是22", Toast.LENGTH_SHORT).show();
                        actionMode.finish();//收起操作菜单
                        break;
                    case R.id.Informal33:
                        Toast.makeText(MainActivity.this, "点击的是33", Toast.LENGTH_SHORT).show();
                        actionMode.finish();
                        break;
                }
                return false;//返回true则系统的"复制"、"搜索"之类的item将无效,只有自定义item有响应
            }

            @Override
            public void onDestroyActionMode(ActionMode actionMode) {

            }

            @Override
            public void onGetContentRect(ActionMode mode, View view, Rect outRect) {
                //可选  用于改变弹出菜单的位置
                super.onGetContentRect(mode, view, outRect);
            }
        };
    }
增加自定义item
增加自定义item

上面这样写的话会有系统的“复制”、“全选”、“搜索”等item,以及其他APP提供的操作item,如果你(或者你们产品经理)傲娇的想要屏蔽所有非本APP自定义item,可以改成这样

  @Override
  public boolean onCreateActionMode(ActionMode actionMode, Menu menu) {
        return true;//返回false则不会显示弹窗
  }

  @Override
  public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) {
         MenuInflater menuInflater = actionMode.getMenuInflater();
         menu.clear();
         menuInflater.inflate(R.menu.selection_action_menu,menu);
         return true;
  }
只有自定义item

然后我们为TextView和EditText设置文本选择操作回调

  textView.setCustomSelectionActionModeCallback(textSelectionActionModeCallback);
  editText.setCustomSelectionActionModeCallback(textSelectionActionModeCallback);

EditText在还有一个插入操作菜单可以设置

  edittext.setCustomInsertionActionModeCallback(textSelectionActionModeCallback);
EditText插入操作菜单

MIUI上小米重写了EditText和TextView中的文本选择菜单,上面这些代码修改无效。好吧,算你狠。 = =、

2.为其他APP提供文本选择操作

一般剪切板、翻译、搜索、记事本类APP会提供这种功能,为用户提供便捷操作,同时也刷下自己的存在感。

我先建了一个继承自Activity的CustomTextProcessingActivity,简单写了下布局,我这因为拖延症的常见并发症——懒癌发作,代码就不贴出来了。

然后按照基本法到清单文件里去注册一下

<activity android:name=".CustomTextProcessingActivity">
    <intent-filter>
        <action android:name="android.intent.action.PROCESS_TEXT"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <data android:mimeType="text/plain"/>
    </intent-filter>
</activity>

这里可以为activity自定义主题和标签,标签值就是文本选择操作菜单中出现的item名。默认就是APP名称"MY APPLICATION"。如果你想让这个操作只出现在本APP中,可以设置android:exported=”false”。

回到CustomTextProcessingActivity中,获取用户选择的文本只需要这样

 CharSequence text = getIntent().getCharSequenceExtra(Intent.EXTRA_PROCESS_TEXT);

我们还可以判断文本是否可编辑

 boolean isReadonly = getIntent().getBooleanExtra(Intent.EXTRA_PROCESS_TEXT_READONLY, false);

我们点击“MY APPLICATION”的时候,其实系统是通过是 startActivityForResult() 来启动的CustomTextProcessingActivity,所以我们可以返回一个文本。当选中的文本可编辑时(如EditText中的文字),系统会替换文字;不可编辑时,系统会通过toast的方式展示出来。

   //返回一个文本
   Intent intent = new Intent();
   intent.putExtra(Intent.EXTRA_PROCESS_TEXT, "这是替换的文字");
   setResult(RESULT_OK, intent);

这个界面写成弹窗的样式感觉更好,看大家的具体设计了。

在我一加的氢OS上,EditText在setCustomSelectionActionModeCallback()之后就只有第一部分中自定义的item以及系统的“复制”等基础item,本APP和其他的三方APP提供的操作item都无法显示。华为上是不显示第二部分中APP提供的操作item,其他的正常显示。而一加和华为上的TextView都是正常的。

至于小米,EditText和TextView不会显示三方APP提供的操作item。但是WebView中选择文字弹出来的还是原生文本选择操作菜单,有三方APP的操作item,估计是小米程序猿漏掉了


这篇文章周末就开始写了,现在的时间是周三。嗯...还行,拖得时间不算太长...

欢迎拖延症病友交流病情。。。。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 151,511评论 1 330
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 64,495评论 1 273
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 101,595评论 0 225
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 42,558评论 0 190
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 50,715评论 3 270
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 39,672评论 1 192
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,112评论 2 291
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 29,837评论 0 181
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 33,417评论 0 228
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 29,928评论 2 232
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,316评论 1 242
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 27,773评论 2 234
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,253评论 3 220
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,827评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,440评论 0 180
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 34,523评论 2 249
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 34,583评论 2 249

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 170,471评论 25 707
  • 内容抽屉菜单ListViewWebViewSwitchButton按钮点赞按钮进度条TabLayout图标下拉刷新...
    皇小弟阅读 46,319评论 22 663
  • 今天是妹妹的生日,妈妈买了一个蛋糕。 牛哥哥和姐姐围在哪 大家伙开开心心一起唱生日歌 一个三磅的蛋糕,没几分钟就就...
    冰雪中盛开的花阅读 255评论 0 0
  • 晨曦的第一杯水,排出毒素,你差青汁。 餐后的第一杯水,养护肠胃,你差青汁。 午后的第一杯水,清醒头脑,你差青汁。 ...
    小蜗先生阅读 227评论 0 1
  • 1.RxSwift常见操作 never never就是创建一个sequence,但是不发出任何事件信号。 empt...
    CoderLWG阅读 513评论 0 2