Android官方控件中,EditText中的文字默认长按呼出文本选择菜单,而TextView需要设置android:textIsSelectable=”true”。
在开发中,如果我们需要自己处理文本菜单的事件,在6.0以下版本中,我们可以自定义TextView或EditText,重onTextContextMenuItem(int id)方法,根据id做相应的处理。在6.0以下版本中,文本菜单按钮大部分只有全选、复制、剪切、粘贴。
注意事项:
1.在我们操作完菜单按钮后,可能菜单按钮和文字选中的样式,都没有回复到原状态。查看源码:
/**
* @hide
*/
protected void stopTextActionMode() {
if (mEditor != null) {
mEditor.stopTextActionMode();
}
}
尝试过想用反射获取Editor类,调用StopTextActionMode()消除菜单和选中样式,但是Editor是系统类,不能导入,所以失败。经过多次查找,最后是给控件重新赋值:setText(getText());
解决的。
》在高版本中可能有其他的按钮,可能有些按钮我们用不上,不想让他们显示。我们可以自定以文本选择菜单。只需要为TextView或者EditText设置setCustomSelectionActionModeCallback(ActionMode.Callback callBack)方法,并且在方法里实现ActionMode.Callback()或ActionMode.Callback2()接口。ActionMode.Callback()和ActionMode.Callback2()接口的主要内容相同,只是Callback2中多了一个onGetContentRect()方法,重写可以改变弹出菜单的位置。另外,Callback2需要判断sdk23及以上版本,Callback()不用,但是在6.0以下系统中实际是无效的。
》我们先在res下的menu文件夹里新建一个菜单文件,我把它命名为edit_menu.xml,内容如下:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/select_all" android:title="全选"/>
<item android:id="@+id/select_copy" android:title="复制"/>
<item android:id="@+id/select_cut" android:title="剪切"/>
<item android:id="@+id/select_paste" android:title="粘贴"/>
</menu>
然后我们完成文本选择菜单的修改
private class MyActionModeCallback implements ActionMode.Callback {
private Menu mMenu;
@Override
public boolean onCreateActionMode(ActionMode actionMode, Menu menu) {
MenuInflater menuInflater = actionMode.getMenuInflater();
menu.clear();
menuInflater.inflate(R.menu.edit_menu, menu);
return true;
}
@Override
public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) {
//菜单创建完成以后获取到其对象,便于后续操作
this.mMenu = menu;
return true;
}
@Override
public boolean onActionItemClicked(ActionMode actionMode, MenuItem menuItem) {
final int min = getSelectMin();
final int max = getSelectMax();
switch (menuItem.getItemId()) {
case R.id.select_all:
//全选
selectAll();
Toast.makeText(getContext(), "完成全选", Toast.LENGTH_SHORT).show();
break;
case R.id.select_copy:
setPrivateClip(getTransformedText(min, max));
stopTextActionMode();
//setText(selectText)是为了后面的this.mMenu.close()起作用
Toast.makeText(getContext(), "选中的内容已复制到剪切板 + copy", Toast.LENGTH_SHORT).show();
this.mMenu.close();
break;
case R.id.select_cut:
//剪切
setPrivateClip(getTransformedText(min, max));
deleteText_internal(min, max);
Toast.makeText(getContext(), "选中的内容已剪切到剪切板 + cut", Toast.LENGTH_SHORT).show();
this.mMenu.close();
break;
case R.id.select_paste:
//获取剪切班管理者
normalPaste(min , max , true);
this.mMenu.close();
Toast.makeText(getContext(), "粘贴完成 + paste", Toast.LENGTH_SHORT).show();
break;
}
return true;
}
@Override
public void onDestroyActionMode(ActionMode actionMode) {
}
}
上面这样写的话会有系统的“复制”、“全选”、“搜索”等item,以及其他APP提供的操作item,如果你(或者你们产品经理)傲娇的想要屏蔽所有非本APP自定义item,可以改成这样:
@Override
public boolean onCreateActionMode(ActionMode actionMode, Menu menu) {
return true;
}
@Override
public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) {
//菜单创建完成以后获取到其对象,便于后续操作
this.mMenu = menu;
MenuInflater menuInflater = actionMode.getMenuInflater();
menu.clear();
menuInflater.inflate(R.menu.edit_menu, menu);
return true;
}
EditText在还有一个插入操作菜单可以设置:
edittext.setCustomInsertionActionModeCallback(textSelectionActionModeCallback);