Devices with Android + MIUI and setCustomSelectionActionModeCallback
AndroidTextviewAndroid Problem Overview
I'm trying to create custom selection menu but it does not work on a device with rom MIUI and Android 6. The result is common menu with copy
and select all
items. On other devices and simulators under clean Android it works just fine.
The code:
textViewTop.setCustomSelectionActionModeCallback(new android.view.ActionMode.Callback() {
@Override
public boolean onCreateActionMode(android.view.ActionMode mode, Menu menu) {
Log.d(LOG_TAG, "onCreateActionMode");
return true;
}
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
Log.d(LOG_TAG, "onPrepareActionMode");
menu.clear();
int quote_quick = R.drawable.ic_desktop_mac_black_24dp;
int quote_add = R.drawable.ic_computer_black_24dp;
int copy = R.drawable.ic_devices_other_black_24dp;
menu.add(Menu.NONE, QUOTE_START, 3, "").setIcon(quote_quick).setShowAsActionFlags(MenuItem.SHOW_AS_ACTION_ALWAYS);
menu.add(Menu.NONE, QUOTE_ADD, 2, "").setIcon(quote_add).setShowAsActionFlags(MenuItem.SHOW_AS_ACTION_ALWAYS);
menu.add(Menu.NONE, CUSTOM_COPY, 1, "").setIcon(copy).setShowAsActionFlags(MenuItem.SHOW_AS_ACTION_ALWAYS);
return false;
}
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
return false;
}
@Override
public void onDestroyActionMode(ActionMode mode) {
}
});
Android Solutions
Solution 1 - Android
So I figured out a workaround, but it makes sense only if you absolutely need it to work on MIUI devices. It's generally a little awkward:
I noticed that the Wikipedia app has custom actions working on a Xiaomi device, and after looking through the code I found out it works fine when the texts is selected in a WebView
.
You can basically use a WebView
and override onActionModeStarted
in your Activity
Acivity:
String html = "<!DOCTYPE html>\n" +
"<html>\n" +
"<head>\n" +
"</head>\n" +
"<body>\n" +
"\n" +
"<h1>WebView text</h1>\n" +
"\n" +
"</body>\n" +
"</html>\n";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
WebView webView = findViewById(R.id.web_view);
webView.setWebViewClient(new WebViewClient());
webView.loadData(html, "text/html", "UTF-8");
}
@Override
public void onActionModeStarted(ActionMode mode) {
super.onActionModeStarted(mode);
Menu menu = mode.getMenu();
menu.clear();
mode.getMenuInflater().inflate(R.menu.menu_text_select, menu);
}
Menu:
Solution 2 - Android
Just some thoughts. What if you take menu item onCreateOptionsMenu
and change it.
Like this:
public boolean onCreateOptionsMenu(final Menu menu) {
getSupportMenuInflater().inflate(R.menu.main, menu);
new Handler().post( -> {
final View menuItemView = findViewById(R.id.menu_action_item);
...
}
}
Solution 3 - Android
According to https://developer.android.com/guide/topics/ui/menus#CAB you need to create menu in onCreateActionMode.
I made it like this (in kotlin):
val actionModeCallbackA = object : ActionMode.Callback {
override fun onActionItemClicked(mode: ActionMode?, p1: MenuItem?): Boolean {
Log.wtf("ACTION MODE", "onActionItemClicked")
actionModeB = startActionMode(actionModeCallbackB)
return true
}
override fun onCreateActionMode(mode: ActionMode?, menu: Menu?): Boolean {
Log.wtf("ACTION MODE", "onCreateActionMode")
val inflater = mode?.getMenuInflater()
inflater?.inflate(R.menu.context_menu, menu)
return true
}
override fun onPrepareActionMode(p0: ActionMode?, p1: Menu?): Boolean {
Log.wtf("ACTION MODE", "onPrepareActionMode")
return false
}
override fun onDestroyActionMode(p0: ActionMode?) {
Log.wtf("ACTION MODE", "onDestroyActionMode")
actionModeA = null
}
}
Solution 4 - Android
I had similar problem, maybe my solution would help someone. I had to make a view composed of several horizontal neighboring EditText
's, and add ability to paste text to them (one letter of text to one editText)
I used ActionMode.Callback
's approach and it was working fine, except Xiaomi devices. The solution for Xiaomi devices was using OnLongClickListener
on edit texts and create PopupMenu
on long click:
editText.setOnLongClickListener(v -> {
PopupMenu menu = new PopupMenu(context,v);
MenuInflater inflater = menu.getMenuInflater();
inflater.inflate(R.menu.paste_menu_item, menu.getMenu());
menu.setOnMenuItemClickListener(item -> {
pasteText();//some custom function to handle selected action
return false;
});
menu.show();
return true;
});