因?yàn)槲疑砘剂餍行越^癥(拖延癥),不知不覺(jué)中博客已經(jīng)有半年沒(méi)更新了 ( ⊙ o ⊙ )劲装。
正好最近在寫(xiě)文本選擇菜單的功能染突,就整理出了一篇文章啊终,算是我與該死的拖延癥展開(kāi)的殊死搏斗吧。
本文主要寫(xiě)了在Android6.0+版本上甫匹,修改EditText甸鸟、TextView的文本選擇菜單內(nèi)容和為其他APP提供自定義文本操作這兩個(gè)功能。
1.修改EditText和TextView的文本選擇菜單內(nèi)容
Android官方控件中赛惩,EditText中的文字默認(rèn)長(zhǎng)按呼出文本選擇菜單哀墓,而TextView需要設(shè)置android:textIsSelectable="true"。
我們修改文本選擇菜單內(nèi)容喷兼,只需要為TextView或者EditText設(shè)置setCustomSelectionActionModeCallback()方法篮绰,并且在方法里實(shí)現(xiàn)ActionMode.Callback()或ActionMode.Callback2()接口。
ActionMode.Callback()和ActionMode.Callback2()接口的主要內(nèi)容相同季惯,只是Callback2中多了一個(gè)onGetContentRect()方法吠各,重寫(xiě)可以改變彈出菜單的位置。另外勉抓,Callback2需要判斷sdk23及以上版本贾漏,Callback()不用,但是在6.0以下系統(tǒng)中實(shí)際是無(wú)效的藕筋。
我們先在res下的menu文件夾里新建一個(gè)菜單文件纵散,我把它命名為selection_action_menu.xml,內(nèi)容如下
<?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則不會(huì)顯示彈窗
}
@Override
public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) {
return false;
}
@Override
public boolean onActionItemClicked(ActionMode actionMode, MenuItem menuItem) {
//根據(jù)item的ID處理點(diǎn)擊事件
switch (menuItem.getItemId()){
case R.id.Informal22:
Toast.makeText(MainActivity.this, "點(diǎn)擊的是22", Toast.LENGTH_SHORT).show();
actionMode.finish();//收起操作菜單
break;
case R.id.Informal33:
Toast.makeText(MainActivity.this, "點(diǎn)擊的是33", Toast.LENGTH_SHORT).show();
actionMode.finish();
break;
}
return false;//返回true則系統(tǒng)的"復(fù)制"隐圾、"搜索"之類的item將無(wú)效伍掀,只有自定義item有響應(yīng)
}
@Override
public void onDestroyActionMode(ActionMode actionMode) {
}
@Override
public void onGetContentRect(ActionMode mode, View view, Rect outRect) {
//可選 用于改變彈出菜單的位置
super.onGetContentRect(mode, view, outRect);
}
};
}
上面這樣寫(xiě)的話會(huì)有系統(tǒng)的“復(fù)制”、“全選”暇藏、“搜索”等item蜜笤,以及其他APP提供的操作item,如果你(或者你們產(chǎn)品經(jīng)理)傲嬌的想要屏蔽所有非本APP自定義item盐碱,可以改成這樣
@Override
public boolean onCreateActionMode(ActionMode actionMode, Menu menu) {
return true;//返回false則不會(huì)顯示彈窗
}
@Override
public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) {
MenuInflater menuInflater = actionMode.getMenuInflater();
menu.clear();
menuInflater.inflate(R.menu.selection_action_menu,menu);
return true;
}
然后我們?yōu)門extView和EditText設(shè)置文本選擇操作回調(diào)
textView.setCustomSelectionActionModeCallback(textSelectionActionModeCallback);
editText.setCustomSelectionActionModeCallback(textSelectionActionModeCallback);
EditText在還有一個(gè)插入操作菜單可以設(shè)置
edittext.setCustomInsertionActionModeCallback(textSelectionActionModeCallback);
MIUI上小米重寫(xiě)了EditText和TextView中的文本選擇菜單把兔,上面這些代碼修改無(wú)效沪伙。好吧,算你狠县好。 = =围橡、
2.為其他APP提供文本選擇操作
一般剪切板、翻譯聘惦、搜索某饰、記事本類APP會(huì)提供這種功能,為用戶提供便捷操作善绎,同時(shí)也刷下自己的存在感黔漂。
我先建了一個(gè)繼承自Activity的CustomTextProcessingActivity,簡(jiǎn)單寫(xiě)了下布局禀酱,我這因?yàn)橥涎影Y的常見(jiàn)并發(fā)癥——懶癌發(fā)作炬守,代碼就不貼出來(lái)了。
然后按照基本法到清單文件里去注冊(cè)一下
<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自定義主題和標(biāo)簽剂跟,標(biāo)簽值就是文本選擇操作菜單中出現(xiàn)的item名减途。默認(rèn)就是APP名稱"MY APPLICATION"。如果你想讓這個(gè)操作只出現(xiàn)在本APP中曹洽,可以設(shè)置android:exported=”false”鳍置。
回到CustomTextProcessingActivity中,獲取用戶選擇的文本只需要這樣
CharSequence text = getIntent().getCharSequenceExtra(Intent.EXTRA_PROCESS_TEXT);
我們還可以判斷文本是否可編輯
boolean isReadonly = getIntent().getBooleanExtra(Intent.EXTRA_PROCESS_TEXT_READONLY, false);
我們點(diǎn)擊“MY APPLICATION”的時(shí)候送淆,其實(shí)系統(tǒng)是通過(guò)是 startActivityForResult()?來(lái)啟動(dòng)的CustomTextProcessingActivity税产,所以我們可以返回一個(gè)文本。當(dāng)選中的文本可編輯時(shí)(如EditText中的文字)偷崩,系統(tǒng)會(huì)替換文字辟拷;不可編輯時(shí),系統(tǒng)會(huì)通過(guò)toast的方式展示出來(lái)阐斜。
//返回一個(gè)文本
Intent intent = new Intent();
intent.putExtra(Intent.EXTRA_PROCESS_TEXT, "這是替換的文字");
setResult(RESULT_OK, intent);
這個(gè)界面寫(xiě)成彈窗的樣式感覺(jué)更好衫冻,看大家的具體設(shè)計(jì)了。
在我一加的氫OS上谒出,EditText在setCustomSelectionActionModeCallback()之后就只有第一部分中自定義的item以及系統(tǒng)的“復(fù)制”等基礎(chǔ)item隅俘,本APP和其他的三方APP提供的操作item都無(wú)法顯示。華為上是不顯示第二部分中APP提供的操作item,其他的正常顯示笤喳。而一加和華為上的TextView都是正常的为居。
至于小米,EditText和TextView不會(huì)顯示三方APP提供的操作item莉测。但是WebView中選擇文字彈出來(lái)的還是原生文本選擇操作菜單,有三方APP的操作item唧喉,估計(jì)是小米程序猿漏掉了捣卤。
這篇文章周末就開(kāi)始寫(xiě)了忍抽,現(xiàn)在的時(shí)間是周三。嗯...還行董朝,拖得時(shí)間不算太長(zhǎng)...
歡迎拖延癥病友交流病情鸠项。。子姜。祟绊。