Horizontal inflable de menú en el clic largo para la vista web
Hy, Tengo un problema con la selección de webview en longClick. Ya tenía una implementación de un menú personalizado que se lanza en longClick. Pero el menú predeterminado también se está iniciando. Estoy tratando de personalizar el menú predeterminado, pero no estoy sabiendo cómo capturar el clic del usuario en un elemento. He intentado lo siguiente, pero el menú se está convirtiendo en vertical y ocultar la selección, por lo que no puedo seleccionar más palabras o cambiar la selección.
@Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { super.onCreateContextMenu(menu, v, menuInfo); MenuInflater inflater = getMenuInflater(); /* public void inflate (int menuRes, Menu menu) Inflate a menu hierarchy from the specified XML resource. Throws InflateException if there is an error. Parameters menuRes : Resource ID for an XML layout resource to load (eg, R.menu.main_activity) menu : The Menu to inflate into. The items and submenus will be added to this Menu. */ inflater.inflate(R.menu.menu, menu); } @Override public boolean onContextItemSelected(MenuItem item){ // Handle the menu item selection switch(item.getItemId()){ case R.id.dict_menu: // Render the page again Toast.makeText(mContext,"dict_menu",Toast.LENGTH_SHORT).show(); return true; case R.id.q_menu: Toast.makeText(mContext,"q_menu",Toast.LENGTH_SHORT).show(); return true; case R.id.hi_menu: Toast.makeText(mContext,"hi_menu",Toast.LENGTH_SHORT).show(); return true; default: super.onContextItemSelected(item); } return false; }
Con el menú xml como sigue.
- La autenticación de Dropbox deja abierto el navegador
- Android <4.3 WebView https error: Retroceder a SSLv3 porque host es TLS intolerante
- Android - CoordinatorLayout / NestedScrollView / Hide-Show Toolbar / Problema con WebView
- Establecer credenciales en una vista Web de Android mediante una conexión HTTPS segura
- Android WebView no puede cargar archivos de video locales
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal"> <item android:id="@+id/dict_menu" android:title="قاموس" /> <item android:id="@+id/q_menu" android:title="اقتباس" /> <item android:id="@+id/hi_menu" android:title="تظليل" /> </menu>
Por lo tanto, en lugar de tener este resultado: (obtengo este resultado cuando no implemento los siguientes métodos: onCreateContextMenu, onContextItemSelected que me permiten capturar cuando se elige un elemento del menú)
Tengo lo siguiente:
La primera captura de pantalla se recibe cuando uso el código siguiente:
@Override public void onActionModeStarted(ActionMode mode) { System.out.println("onActionModeStarted"); if (mActionMode == null) { mActionMode = mode; //mode.setTitle("Dictionary"); Menu menu = mode.getMenu(); menu.clear(); mode.getMenuInflater().inflate(R.menu.menu, menu);//mode.getMenuInflater().inflate(myMenu, menu); } //System.out.println("onActionModeStarted"); super.onActionModeStarted(mode); } public void onContextualMenuItemClicked(MenuItem item) { System.out.println("onContextualMenuItemClicked"); switch (item.getItemId()) { case R.id.dict_menu: // do some stuff System.out.println("dict_menu"); Toast.makeText(mContext,"dict_menu",Toast.LENGTH_SHORT).show(); break; case R.id.hi_menu: // do some different stuff System.out.println("hi_menu"); Toast.makeText(mContext,"hi_menu",Toast.LENGTH_SHORT).show(); break; case R.id.q_menu: // do some different stuff System.out.println("q_menu"); Toast.makeText(mContext,"q_menu",Toast.LENGTH_SHORT).show(); break; default: // ... super.onContextItemSelected(item); break; } // This will likely always be true, but check it anyway, just in case /*if (mActionMode != null) { mActionMode.finish(); }*/ } @Override public void onActionModeFinished(ActionMode mode) { mActionMode = null; super.onActionModeFinished(mode); System.out.println("onActionModeFinished"); } <?xml version="1.0" encoding="utf-8"?> <!---<menu xmlns:android="http://schemas.android.com/apk/res/android"--> <menu xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal"> <item android:id="@+id/dict_menu" android:onClick="onContextualMenuItemClicked" android:title="قاموس" /> <item android:id="@+id/q_menu" android:onClick="onContextualMenuItemClicked" android:title="اقتباس" /> <item android:id="@+id/hi_menu" android:onClick="onContextualMenuItemClicked" android:title="تظليل" /> </menu>
Esto está causando el error siguiente:
android.view.InflateException: Couldn't resolve menu item onClick handler onContextualMenuItemClicked in class android.app.ContextImpl 08-10 09:01:21.602 4931-4931/ W/System.err: at android.view.MenuInflater$InflatedOnMenuItemClickListener.<init>(MenuInflater.java:243) 08-10 09:01:21.602 4931-4931/ W/System.err: at android.view.MenuInflater$MenuState.setItem(MenuInflater.java:464) 08-10 09:01:21.602 4931-4931/ W/System.err: at android.view.MenuInflater$MenuState.addItem(MenuInflater.java:498) 08-10 09:01:21.602 4931-4931/ W/System.err: at android.view.MenuInflater.parseMenu(MenuInflater.java:191) 08-10 09:01:21.602 4931-4931/ W/System.err: at android.view.MenuInflater.inflate(MenuInflater.java:112) 08-10 09:01:21.602 4931-4931/ W/System.err: at BookReader.onActionModeStarted(BookReader.java:3346) 08-10 09:01:21.602 4931-4931/ W/System.err: at com.android.internal.policy.DecorView.startActionMode(DecorView.java:1034) 08-10 09:01:21.602 4931-4931/ W/System.err: at com.android.internal.policy.DecorView.startActionModeForChild(DecorView.java:982) 08-10 09:01:21.602 4931-4931/ W/System.err: at android.view.ViewGroup.startActionModeForChild(ViewGroup.java:828) 08-10 09:01:21.602 4931-4931/ W/System.err: at android.view.ViewGroup.startActionModeForChild(ViewGroup.java:828) 08-10 09:01:21.602 4931-4931/ W/System.err: at android.view.ViewGroup.startActionModeForChild(ViewGroup.java:828) 08-10 09:01:21.603 4931-4931/ W/System.err: at android.view.ViewGroup.startActionModeForChild(ViewGroup.java:828) 08-10 09:01:21.603 4931-4931/ W/System.err: at android.view.View.startActionMode(View.java:6398) 08-10 09:01:21.603 4931-4931/ W/System.err: at org.chromium.content.browser.SelectionPopupController.showActionModeOrClearOnFailure(SelectionPopupController.java:45) 08-10 09:01:21.603 4931-4931/ W/System.err: at org.chromium.content.browser.ContentViewCore.onSelectionEvent(ContentViewCore.java:579) 08-10 09:01:21.603 4931-4931/ W/System.err: at org.chromium.base.SystemMessageHandler.nativeDoRunLoopOnce(Native Method) 08-10 09:01:21.603 4931-4931/ W/System.err: at org.chromium.base.SystemMessageHandler.handleMessage(SystemMessageHandler.java:7) 08-10 09:01:21.603 4931-4931/ W/System.err: at android.os.Handler.dispatchMessage(Handler.java:102) 08-10 09:01:21.603 4931-4931/ W/System.err: at android.os.Looper.loop(Looper.java:154) 08-10 09:01:21.603 4931-4931/ W/System.err: at android.app.ActivityThread.main(ActivityThread.java:6692) 08-10 09:01:21.603 4931-4931/ W/System.err: at java.lang.reflect.Method.invoke(Native Method) 08-10 09:01:21.603 4931-4931/ W/System.err: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1468) 08-10 09:01:21.603 4931-4931/ W/System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1358) 08-10 09:01:21.603 4931-4931/ W/System.err: Caused by: java.lang.NoSuchMethodException: onContextualMenuItemClicked [interface android.view.MenuItem] 08-10 09:01:21.603 4931-4931/ W/System.err: at java.lang.Class.getMethod(Class.java:1981) 08-10 09:01:21.603 4931-4931/ W/System.err: at java.lang.Class.getMethod(Class.java:1637) 08-10 09:01:21.603 4931-4931/ W/System.err: at android.view.MenuInflater$InflatedOnMenuItemClickListener.<init>(MenuInflater.java:241) 08-10 09:01:21.603 4931-4931/ W/System.err: ... 22 more 08-10 09:01:21.604 4931-4931/ A/chromium: [FATAL:jni_android.cc(243)] Please include Java exception stack in crash report
Por favor, si hay algún código que falta, o cualquier información que es ambiguo, déjame saber para aclararlo, gracias por tu ayuda.
- WebView con un androide IFRAME
- Cómo ocultar la página de error de WebView. ¿Es posible?
- Android webview: detecte una larga pulsación en <a> y <img>
- Detener Android WebView automáticamente creando vínculos (enfocables)
- ¿Por qué WebView es mucho más rápido que un TextView?
- Vista Web de Android: desactive CORS
- WebView provoca el reinicio de la aplicación - Señal fatal 11 (SIGSEGV)
- Problema de redireccionamiento de Webview
Actualizar
De alguna manera me perdí que estaba hablando sobre el menú contextual dentro de un WebView . Mi respuesta a continuación es correcta siempre y cuando usted está hablando de un TextView
, pero no es realmente aplicable a su pregunta real. Aún así, no siento que debería eliminarlo ya que podría ayudar a alguien que esté trabajando con TextView
lugar de WebView
.
En cuanto a cómo resolver esto para WebView
, en realidad es mucho más simple. En cualquier actividad que esté hospedando su WebView
, onActionModeStarted()
, manipule los elementos del menú y asigne a los oyentes a cada uno. Un ejemplo:
@Override public void onActionModeStarted(ActionMode mode) { super.onActionModeStarted(mode); MenuInflater menuInflater = mode.getMenuInflater(); Menu menu = mode.getMenu(); menu.clear(); menuInflater.inflate(R.menu.menu_custom, menu); menu.findItem(R.id.custom_one).setOnMenuItemClickListener(new ToastMenuItemListener(this, mode, "One!")); menu.findItem(R.id.custom_two).setOnMenuItemClickListener(new ToastMenuItemListener(this, mode, "Two!")); menu.findItem(R.id.custom_three).setOnMenuItemClickListener(new ToastMenuItemListener(this, mode, "Three!")); } private static class ToastMenuItemListener implements MenuItem.OnMenuItemClickListener { private final Context context; private final ActionMode actionMode; private final String text; private ToastMenuItemListener(Context context, ActionMode actionMode, String text) { this.context = context; this.actionMode = actionMode; this.text = text; } @Override public boolean onMenuItemClick(MenuItem item) { Toast.makeText(context, text, Toast.LENGTH_SHORT).show(); actionMode.finish(); return true; } }
Original
Si desea controlar el menú contextual que aparece cuando presiona un TextView
, puede utilizar TextView.setCustomSelectionActionModeCallback()
.
Puse una aplicación muy sencilla para demostrar cómo usar esta función.
MainActivity.java
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); TextView text = (TextView) findViewById(R.id.text); CustomActionModeCallback callback = new CustomActionModeCallback(this); text.setCustomSelectionActionModeCallback(callback); } }
Esta es la solución que funcionó para mí, espero que pueda ser útil para alguien.
La única diferencia con la respuesta anterior es que creé el menú de forma dinámica, porque el menú estático por alguna razón no estaba respondiendo a la función menuItemClicked ().
@Override public void onActionModeStarted(ActionMode mode) { System.out.println("onActionModeStarted"); if (mActionMode == null) { mActionMode = mode; //mode.setTitle("Dictionary"); Menu menu = mode.getMenu(); menu.clear(); mode.getMenuInflater().inflate(R.menu.menu, menu); List<MenuItem> menuItems = new ArrayList<>(); // get custom menu item for (int i = 0; i < menu.size(); i++) { menuItems.add(menu.getItem(i)); } menu.clear(); // reset menu item order int size = menuItems.size(); for (int i = 0; i < size; i++) { addMenuItem(menu, menuItems.get(i), i, true); } } //System.out.println("onActionModeStarted"); super.onActionModeStarted(mode); } private void addMenuItem(Menu menu, MenuItem item, int order, boolean isClick){ final MenuItem menuItem = menu.add(item.getGroupId(), item.getItemId(), order, item.getTitle()); menuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS); if (isClick) // set custom menu item click menuItem.setOnMenuItemClickListener(new OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem item) { BookReader.this.menuItemClicked(item); return true; } }); } public void menuItemClicked(MenuItem item) { System.out.println("menuItemClicked"); switch (item.getItemId()) { case R.id.dict_menu: testWV.searchInDict(); if (mActionMode!=null){ mActionMode.finish(); } break; case R.id.hi_menu: testWV.highlightWord(); break; case R.id.q_menu: testWV.copyQuote(); if (mActionMode!=null){ mActionMode.finish(); } break; } }
- Envío de datos a un servidor cuando el dispositivo está conectado a Internet
- Escribir números fraccionarios en Java o Android