vez son solo siempre samsung revertir restablecer predeterminadas predeterminada para las esta eliminar cómo cuales configuracion como cambiar archivo aplicaciones aplicacion abrir android android-webview textselection

son - ¿Cómo anular la selección de texto predeterminada de Android Webview OS 4.1+?



cómo revertir siempre o solo esta vez (9)

En caso de que alguien esté intentando simplemente eliminar la selección de texto predeterminada, tuve el mismo problema en una Samsung Galaxy Tab en Android 4.1.2 y terminé escribiendo mi propia vista WebView :

public class CustomWebView extends WebView { public CustomWebView(Context context) { super(context); this.setUp(context); } public CustomWebView(Context context, AttributeSet attrs) { super(context, attrs); this.setUp(context); } public CustomWebView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); this.setUp(context); } private void setUp(Context context) { this.setOnLongClickListener(new OnLongClickListener() { @Override public boolean onLongClick(View v) { return true; } }); this.setLongClickable(false); } @Override public boolean performLongClick() { return true; } }

y refiriéndolo en mi xml:

<com...CustomWebView android:id="@+id/webview" android:layout_width="fill_parent" android:layout_height="fill_parent" />

Antes de publicar esta pregunta, he buscado mucho pero no pude encontrar respuestas claras sobre este problema.

Tengo que anular la selección de texto predeterminada de la vista web de Android y mostrar mis opciones de diálogo de selección de texto personalizado. He intentado este project código de ejemplo.

Este proyecto de muestra funciona en los siguientes dispositivos y emuladores:

  • Acer Iconia a500 tablet: 10 pulgadas: sistema operativo Android - 3.0
  • Acer Iconia a500 tablet: 10 pulgadas: sistema operativo Android - 3.2
  • Samsung Galaxy Tab: 10 pulgadas: sistema operativo Android - 4.0
  • Samsung Galaxy Tab: 7 pulgadas: sistema operativo Android - 4.0
  • Emulador: Skin-WVGA800: SO Android - 4.1.2

No funciona en los siguientes dispositivos:

  • Samsung Galaxy Tab: 10 pulgadas: sistema operativo Android - 4.1.2
  • Samsung Galaxy Tab: 7 pulgadas: sistema operativo Android - 4.1.2

En las versiones 4.1 y 4.1+ de Android OS, en lugar de mostrar mi diálogo de opción de selección de texto personalizado, muestra la barra de acción predeterminada del sistema Android para la selección de texto.

He buscado mucho en esto, muchos sugirieron usar el método onLongClick () de la interface

Ya hice una pregunta en este foro. Por favor vea este link . Con las respuestas a estas preguntas, puedo clonar el evento OnLongClick () pero no puedo detener la barra de acción de selección de texto predeterminada.

Para este escenario tengo algunas preguntas.

1. ¿Por qué el método onLongClick () deja de funcionar para un dispositivo que se ejecuta en la versión 4.1+ de Android OS?

2. ¿Cómo detener la barra de acción de selección de texto predeterminada al presionar el texto desde webview?

Esta es mi clase de webview personalizada.

package com.epubreader.ebook; import org.json.JSONException; import org.json.JSONObject; import android.app.Activity; import android.content.Context; import android.graphics.Rect; import android.graphics.Region; import android.os.Handler; import android.os.Message; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.util.Log; import android.view.ContextMenu; import android.view.Display; import android.view.GestureDetector; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.View.OnLongClickListener; import android.view.View.OnTouchListener; import android.view.ViewGroup; import android.view.WindowManager; import android.webkit.WebView; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.Toast; import com.epubreader.R; import com.epubreader.drag.DragController; import com.epubreader.drag.DragLayer; import com.epubreader.drag.DragListener; import com.epubreader.drag.DragSource; import com.epubreader.drag.MyAbsoluteLayout; import com.epubreader.menu.menuAnimationHelper; import com.epubreader.textselection.WebTextSelectionJSInterface; import com.epubreader.textselectionoverlay.ActionItem; import com.epubreader.textselectionoverlay.QuickAction; import com.epubreader.textselectionoverlay.QuickAction.OnDismissListener; public class CustomWebView extends WebView implements WebTextSelectionJSInterface, OnTouchListener , OnLongClickListener, OnDismissListener, DragListener{ /** The logging tag. */ private static final String TAG = "CustomWebView"; /** Context. */ protected Context ctx; /** The context menu. */ private QuickAction mContextMenu; /** The drag layer for selection. */ private DragLayer mSelectionDragLayer; /** The drag controller for selection. */ private DragController mDragController; /** The start selection handle. */ private ImageView mStartSelectionHandle; /** the end selection handle. */ private ImageView mEndSelectionHandle; /** The selection bounds. */ private Rect mSelectionBounds = null; /** The previously selected region. */ protected Region lastSelectedRegion = null; /** The selected range. */ protected String selectedRange = ""; /** The selected text. */ protected String selectedText = ""; /** Javascript interface for catching text selection. */ /** Selection mode flag. */ protected boolean inSelectionMode = false; /** Flag to stop from showing context menu twice. */ protected boolean contextMenuVisible = false; /** The current content width. */ protected int contentWidth = 0; /** Identifier for the selection start handle. */ private final int SELECTION_START_HANDLE = 0; /** Identifier for the selection end handle. */ private final int SELECTION_END_HANDLE = 1; /** Last touched selection handle. */ private int mLastTouchedSelectionHandle = -1; /** Variables for Left & Right Menu ***/ private View menuView; private LinearLayout toiLay; private menuAnimationHelper _menuAnimationHelper; private TocTranslateAnimation _tocTranslateAnimation; private CustomWebView _customWebView; public CustomWebView(Context context) { super(context); this.ctx = context; this.setup(context); } public CustomWebView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); this.ctx = context; this.setup(context); } public CustomWebView(Context context, AttributeSet attrs) { super(context, attrs); this.ctx = context; this.setup(context); } //***************************************************** //* //* Touch Listeners //* //***************************************************** private boolean mScrolling = false; private float mScrollDiffY = 0; private float mLastTouchY = 0; private float mScrollDiffX = 0; private float mLastTouchX = 0; @Override public boolean onTouch(View v, MotionEvent event) { float xPoint = getDensityIndependentValue(event.getX(), ctx) / getDensityIndependentValue(this.getScale(), ctx); float yPoint = getDensityIndependentValue(event.getY(), ctx) / getDensityIndependentValue(this.getScale(), ctx); // TODO: Need to update this to use this.getScale() as a factor. //Log.d(TAG, "onTouch " + xPoint + " , " + yPoint); closeMenu(); if(event.getAction() == MotionEvent.ACTION_DOWN){ final String startTouchUrl = String.format("javascript:android.selection.startTouch(%f, %f);", xPoint, yPoint); mLastTouchX = xPoint; mLastTouchY = yPoint; ((Activity)this.ctx).runOnUiThread(new Runnable() { @Override public void run() { loadUrl(startTouchUrl); } }); // This two line clones the onLongClick() longClickHandler.removeCallbacks(longClickRunnable); longClickHandler.postDelayed(longClickRunnable,300); } else if(event.getAction() == MotionEvent.ACTION_UP){ // Check for scrolling flag if(!mScrolling){ this.endSelectionMode(); } // This line clones the onLongClick() longClickHandler.removeCallbacks(longClickRunnable); mScrollDiffX = 0; mScrollDiffY = 0; mScrolling = false; }else if(event.getAction() == MotionEvent.ACTION_MOVE){ mScrollDiffX += (xPoint - mLastTouchX); mScrollDiffY += (yPoint - mLastTouchY); mLastTouchX = xPoint; mLastTouchY = yPoint; // Only account for legitimate movement. if(Math.abs(mScrollDiffX) > 10 || Math.abs(mScrollDiffY) > 10){ mScrolling = true; } // This line clones the onLongClick() longClickHandler.removeCallbacks(longClickRunnable); } // If this is in selection mode, then nothing else should handle this touch return false; } /** * Pass References of Left & Right Menu */ public void initMenu(LinearLayout _toiLay,View _menuView,menuAnimationHelper menuAnimationHelper, TocTranslateAnimation tocTranslateAnimation){ toiLay = _toiLay; menuView = _menuView; _menuAnimationHelper = menuAnimationHelper; _tocTranslateAnimation = tocTranslateAnimation; } private void closeMenu(){ if(_menuAnimationHelper != null && _menuAnimationHelper.isMenuOpenBool){ _menuAnimationHelper.close(menuView); _menuAnimationHelper.isMenuOpenBool = false; } if(_tocTranslateAnimation != null && _tocTranslateAnimation.isTocListOpenBool){ _tocTranslateAnimation.close(toiLay); _tocTranslateAnimation.isTocListOpenBool = false; } } public void removeOverlay(){ Log.d("JsHandler", "in java removeOverlay" + mScrolling); this.endSelectionMode(); mScrollDiffX = 0; mScrollDiffY = 0; mScrolling = false; } @Override public boolean onLongClick(View v){ Log.d(TAG, "from webView onLongClick "); mScrolling = true; ((Activity)this.ctx).runOnUiThread(new Runnable() { @Override public void run() { loadUrl("javascript:android.selection.longTouch()"); } }); Toast.makeText(ctx, "Long click is clicked ", Toast.LENGTH_LONG).show(); // Don''t let the webview handle it return true; } //***************************************************** //* //* Setup //* //***************************************************** ContextMenu.ContextMenuInfo contextMenuInfo; /** * Setups up the web view. * @param context */ protected void setup(Context context){ // On Touch Listener this.setOnTouchListener(this); this.setClickable(false); this.setLongClickable(true); this.setOnLongClickListener(this); contextMenuInfo = this.getContextMenuInfo(); // Webview setup this.getSettings().setJavaScriptEnabled(true); this.getSettings().setJavaScriptCanOpenWindowsAutomatically(true); // Create the selection handles createSelectionLayer(context); // Set to the empty region Region region = new Region(); region.setEmpty(); _customWebView = this; this.lastSelectedRegion = region; } /** * To clone OnLongClick Listener because its not responding for version 4.1 */ public Runnable longClickRunnable = new Runnable() { public void run() { longClickHandler.sendEmptyMessage(0); } }; public Handler longClickHandler = new Handler(){ public void handleMessage(Message m){ _customWebView.loadUrl("javascript:android.selection.longTouch();"); mScrolling = true; } }; public WebTextSelectionJSInterface getTextSelectionJsInterface(){ return this; } //***************************************************** //* //* Selection Layer Handling //* //***************************************************** /** * Creates the selection layer. * * @param context */ protected void createSelectionLayer(Context context){ LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); this.mSelectionDragLayer = (DragLayer) inflater.inflate(R.layout.selection_drag_layer, null); // Make sure it''s filling parent this.mDragController = new DragController(context); this.mDragController.setDragListener(this); this.mDragController.addDropTarget(mSelectionDragLayer); this.mSelectionDragLayer.setDragController(mDragController); this.mStartSelectionHandle = (ImageView) this.mSelectionDragLayer.findViewById(R.id.startHandle); this.mStartSelectionHandle.setTag(new Integer(SELECTION_START_HANDLE)); this.mEndSelectionHandle = (ImageView) this.mSelectionDragLayer.findViewById(R.id.endHandle); this.mEndSelectionHandle.setTag(new Integer(SELECTION_END_HANDLE)); OnTouchListener handleTouchListener = new OnTouchListener(){ @Override public boolean onTouch(View v, MotionEvent event) { boolean handledHere = false; final int action = event.getAction(); // Down event starts drag for handle. if (action == MotionEvent.ACTION_DOWN) { handledHere = startDrag (v); mLastTouchedSelectionHandle = (Integer) v.getTag(); } return handledHere; } }; this.mStartSelectionHandle.setOnTouchListener(handleTouchListener); this.mEndSelectionHandle.setOnTouchListener(handleTouchListener); } /** * Starts selection mode on the UI thread */ private Handler startSelectionModeHandler = new Handler(){ public void handleMessage(Message m){ if(mSelectionBounds == null) return; addView(mSelectionDragLayer); drawSelectionHandles(); int contentHeight = (int) Math.ceil(getDensityDependentValue(getContentHeight(), ctx)); // Update Layout Params ViewGroup.LayoutParams layerParams = mSelectionDragLayer.getLayoutParams(); layerParams.height = contentHeight; layerParams.width = contentWidth; mSelectionDragLayer.setLayoutParams(layerParams); } }; /** * Starts selection mode. * * @param selectionBounds */ public void startSelectionMode(){ this.startSelectionModeHandler.sendEmptyMessage(0); } // Ends selection mode on the UI thread private Handler endSelectionModeHandler = new Handler(){ public void handleMessage(Message m){ //Log.d("TableContentsWithDisplay", "in endSelectionModeHandler"); removeView(mSelectionDragLayer); if(getParent() != null && mContextMenu != null && contextMenuVisible){ // This will throw an error if the webview is being redrawn. // No error handling needed, just need to stop the crash. try{ mContextMenu.dismiss(); } catch(Exception e){ } } mSelectionBounds = null; mLastTouchedSelectionHandle = -1; try { ((Activity)ctx).runOnUiThread(new Runnable() { @Override public void run() { loadUrl("javascript: android.selection.clearSelection();"); } }); } catch (Exception e) { // TODO: handle exception } } }; /** * Ends selection mode. */ public void endSelectionMode(){ this.endSelectionModeHandler.sendEmptyMessage(0); } /** * Calls the handler for drawing the selection handles. */ private void drawSelectionHandles(){ this.drawSelectionHandlesHandler.sendEmptyMessage(0); } /** * Handler for drawing the selection handles on the UI thread. */ private Handler drawSelectionHandlesHandler = new Handler(){ public void handleMessage(Message m){ MyAbsoluteLayout.LayoutParams startParams = (com.epubreader.drag.MyAbsoluteLayout.LayoutParams) mStartSelectionHandle.getLayoutParams(); startParams.x = (int) (mSelectionBounds.left - mStartSelectionHandle.getDrawable().getIntrinsicWidth()); startParams.y = (int) (mSelectionBounds.top - mStartSelectionHandle.getDrawable().getIntrinsicHeight()); // Stay on screen. startParams.x = (startParams.x < 0) ? 0 : startParams.x; startParams.y = (startParams.y < 0) ? 0 : startParams.y; mStartSelectionHandle.setLayoutParams(startParams); MyAbsoluteLayout.LayoutParams endParams = (com.epubreader.drag.MyAbsoluteLayout.LayoutParams) mEndSelectionHandle.getLayoutParams(); endParams.x = (int) mSelectionBounds.right; endParams.y = (int) mSelectionBounds.bottom; endParams.x = (endParams.x < 0) ? 0 : endParams.x; endParams.y = (endParams.y < 0) ? 0 : endParams.y; mEndSelectionHandle.setLayoutParams(endParams); } }; /** * Checks to see if this view is in selection mode. * @return */ public boolean isInSelectionMode(){ return this.mSelectionDragLayer.getParent() != null; } //***************************************************** //* //* DragListener Methods //* //***************************************************** /** * Start dragging a view. * */ private boolean startDrag (View v) { // Let the DragController initiate a drag-drop sequence. // I use the dragInfo to pass along the object being dragged. // I''m not sure how the Launcher designers do this. Object dragInfo = v; mDragController.startDrag (v, mSelectionDragLayer, dragInfo, DragController.DRAG_ACTION_MOVE); return true; } @Override public void onDragStart(DragSource source, Object info, int dragAction) { // TODO Auto-generated method stub } @Override@SuppressWarnings("deprecation") public void onDragEnd() { // TODO Auto-generated method stub MyAbsoluteLayout.LayoutParams startHandleParams = (MyAbsoluteLayout.LayoutParams) this.mStartSelectionHandle.getLayoutParams(); MyAbsoluteLayout.LayoutParams endHandleParams = (MyAbsoluteLayout.LayoutParams) this.mEndSelectionHandle.getLayoutParams(); float scale = getDensityIndependentValue(this.getScale(), ctx); float startX = startHandleParams.x - this.getScrollX(); float startY = startHandleParams.y - this.getScrollY(); float endX = endHandleParams.x - this.getScrollX(); float endY = endHandleParams.y - this.getScrollY(); startX = getDensityIndependentValue(startX, ctx) / scale; startY = getDensityIndependentValue(startY, ctx) / scale; endX = getDensityIndependentValue(endX, ctx) / scale; endY = getDensityIndependentValue(endY, ctx) / scale; if(mLastTouchedSelectionHandle == SELECTION_START_HANDLE && startX > 0 && startY > 0){ final String saveStartString = String.format("javascript: android.selection.setStartPos(%f, %f);", startX, startY); ((Activity)ctx).runOnUiThread(new Runnable() { @Override public void run() { loadUrl(saveStartString); } }); } if(mLastTouchedSelectionHandle == SELECTION_END_HANDLE && endX > 0 && endY > 0){ final String saveEndString = String.format("javascript: android.selection.setEndPos(%f, %f);", endX, endY); ((Activity)ctx).runOnUiThread(new Runnable() { @Override public void run() { loadUrl(saveEndString); } }); } } //***************************************************** //* //* Context Menu Creation //* //***************************************************** /** * Shows the context menu using the given region as an anchor point. * @param region */ private void showContextMenu(Rect displayRect){ // Don''t show this twice if(this.contextMenuVisible){ return; } // Don''t use empty rect //if(displayRect.isEmpty()){ if(displayRect.right <= displayRect.left){ return; } //Copy action item ActionItem buttonOne = new ActionItem(); buttonOne.setTitle("HighLight"); buttonOne.setActionId(1); //buttonOne.setIcon(getResources().getDrawable(R.drawable.menu_search)); //Highlight action item ActionItem buttonTwo = new ActionItem(); buttonTwo.setTitle("Note"); buttonTwo.setActionId(2); //buttonTwo.setIcon(getResources().getDrawable(R.drawable.menu_info)); ActionItem buttonThree = new ActionItem(); buttonThree.setTitle("Help"); buttonThree.setActionId(3); //buttonThree.setIcon(getResources().getDrawable(R.drawable.menu_eraser)); // The action menu mContextMenu = new QuickAction(this.getContext()); mContextMenu.setOnDismissListener(this); // Add buttons mContextMenu.addActionItem(buttonOne); mContextMenu.addActionItem(buttonTwo); mContextMenu.addActionItem(buttonThree); //setup the action item click listener mContextMenu.setOnActionItemClickListener(new QuickAction.OnActionItemClickListener() { @Override public void onItemClick(QuickAction source, int pos, int actionId) { if (actionId == 1) { callHighLight(); } else if (actionId == 2) { callNote(); } else if (actionId == 3) { // Do Button 3 stuff Log.i(TAG, "Hit Button 3"); } contextMenuVisible = false; } }); this.contextMenuVisible = true; mContextMenu.show(this, displayRect); } private void callHighLight(){ ((Activity)this.ctx).runOnUiThread(new Runnable() { @Override public void run() { loadUrl("javascript:init_txt_selection_event()"); loadUrl("javascript:highlightme_("+0+")"); } }); } private void callNote(){ ((Activity)this.ctx).runOnUiThread(new Runnable() { @Override public void run() { loadUrl("javascript:init_txt_selection_event()"); loadUrl("javascript:fnGetUserAddedNote(''1'')"); } }); } //***************************************************** //* //* OnDismiss Listener //* //***************************************************** /** * Clears the selection when the context menu is dismissed. */ public void onDismiss(){ //clearSelection(); this.contextMenuVisible = false; } //***************************************************** //* //* Text Selection Javascript Interface Listener //* //***************************************************** /** * The user has started dragging the selection handles. */ public void tsjiStartSelectionMode(){ this.startSelectionMode(); } /** * The user has stopped dragging the selection handles. */ public void tsjiEndSelectionMode(){ this.endSelectionMode(); } /** * The selection has changed * @param range * @param text * @param handleBounds * @param menuBounds * @param showHighlight * @param showUnHighlight */@SuppressWarnings("deprecation") public void tsjiSelectionChanged(String range, String text, String handleBounds, String menuBounds){ try { //Log.d(TAG, "tsjiSelectionChanged :- handleBounds " + handleBounds); JSONObject selectionBoundsObject = new JSONObject(handleBounds); float scale = getDensityIndependentValue(this.getScale(), ctx); Rect handleRect = new Rect(); handleRect.left = (int) (getDensityDependentValue(selectionBoundsObject.getInt("left"), getContext()) * scale); handleRect.top = (int) (getDensityDependentValue(selectionBoundsObject.getInt("top"), getContext()) * scale); handleRect.right = (int) (getDensityDependentValue(selectionBoundsObject.getInt("right"), getContext()) * scale); handleRect.bottom = (int) (getDensityDependentValue(selectionBoundsObject.getInt("bottom"), getContext()) * scale); this.mSelectionBounds = handleRect; this.selectedRange = range; this.selectedText = text; JSONObject menuBoundsObject = new JSONObject(menuBounds); Rect displayRect = new Rect(); displayRect.left = (int) (getDensityDependentValue(menuBoundsObject.getInt("left"), getContext()) * scale); displayRect.top = (int) (getDensityDependentValue(menuBoundsObject.getInt("top") - 25, getContext()) * scale); displayRect.right = (int) (getDensityDependentValue(menuBoundsObject.getInt("right"), getContext()) * scale); displayRect.bottom = (int) (getDensityDependentValue(menuBoundsObject.getInt("bottom") + 25, getContext()) * scale); if(!this.isInSelectionMode()){ this.startSelectionMode(); } // This will send the menu rect this.showContextMenu(displayRect); drawSelectionHandles(); } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * Receives the content width for the page. */ public void tsjiSetContentWidth(float contentWidth){ this.contentWidth = (int) this.getDensityDependentValue(contentWidth, ctx); } //***************************************************** //* //* Density Conversion //* //***************************************************** /** * Returns the density dependent value of the given float * @param val * @param ctx * @return */ public float getDensityDependentValue(float val, Context ctx){ // Get display from context Display display = ((WindowManager) ctx.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay(); // Calculate min bound based on metrics DisplayMetrics metrics = new DisplayMetrics(); display.getMetrics(metrics); return val * (metrics.densityDpi / 160f); } /** * Returns the density independent value of the given float * @param val * @param ctx * @return */ public float getDensityIndependentValue(float val, Context ctx){ // Get display from context Display display = ((WindowManager) ctx.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay(); // Calculate min bound based on metrics DisplayMetrics metrics = new DisplayMetrics(); display.getMetrics(metrics); return val / (metrics.densityDpi / 160f); }

}

¡Gracias por adelantado!


He podido resolver esto. También me enfrentaba a este problema y no podía encontrar ninguna solución en la web.

Por lo tanto, si configura un oyente LongClick, la vista web dejará de mostrar la selección. Después de profundizar en el código de Webview, descubrí que estaba llamando al método startRunMode de WebView y que pasaba una instancia de la clase SelectActionCallbackMode.

Simplemente extendí la clase de Webview y anulé el método startRunMode de esta manera:

public ActionMode startActionMode(ActionMode.Callback callback) { actionModeCallback = new CustomizedSelectActionModeCallback(); return super.startActionMode(actionModeCallback); }

Esto obligó a la vista web a mostrar mi devolución de llamada en lugar de mostrar la predeterminada de webview. Esto aseguró que la selección funcionara tan bien como antes y mi CAB se mostrara cada vez que se hizo la selección. La única advertencia fue que tuve que escribir un código para despedir al CAB yo mismo.

Probado en dispositivos 4.1, 4.2 y 4.3.

Espero que esto ayude.


Me doy cuenta de que esta es una pregunta antigua, pero no hay una respuesta aceptada, y ninguna de las respuestas proporcionadas tiene muchos votos.

He logrado lo que está intentando lograr al crear una devolución de llamada de modo de acción personalizada. Esto permite la creación de una barra de acción contextual personalizada (CAB) cuando (en el caso de un WebView ) un usuario hace clic largo en la vista. NOTA: Esto solo funciona en 4.0+ y una pieza solo funciona en 4.4.

Cree un nuevo archivo XML de Android que contenga el diseño de su menú personalizado. Aquí está el mío (context_menu.xml) como ejemplo:

<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android" > <item android:id="@+id/copy" android:icon="@drawable/ic_action_copy" android:showAsAction="always" <!-- Forces this button to be shown --> android:title="@string/copy"> </item> <item android:id="@+id/button2" android:icon="@drawable/menu_button2icon" android:showAsAction="ifRoom" <!-- Show if there is room on the screen--> android:title="@string/button2"> </item> <!-- Add as many more items as you want. Note that if you use "ifRoom", an overflow menu will populate to hold the action items that did not fit in the action bar. --> </menu>

Ahora que el menú está definido, cree una devolución de llamada para él:

public class CustomWebView extends WebView { private ActionMode.Callback mActionModeCallback; private class CustomActionModeCallback implements ActionMode.Callback { // Called when the action mode is created; startActionMode() was called @Override public boolean onCreateActionMode(ActionMode mode, Menu menu) { // Inflate a menu resource providing context menu items MenuInflater inflater = mode.getMenuInflater(); inflater.inflate(R.menu.context_menu, menu); return true; } // Called each time the action mode is shown. // Always called after onCreateActionMode, but // may be called multiple times if the mode is invalidated. @Override public boolean onPrepareActionMode(ActionMode mode, Menu menu) { // Note: This is called every time the selection handlebars move. return false; // Return false if nothing is done } // Called when the user selects a contextual menu item @Override public boolean onActionItemClicked(ActionMode mode, MenuItem item) { switch (item.getItemId()) { case R.id.copy: // Do some stuff for this button mode.finish(); // Action picked, so close the CAB return true; case R.id.button2: // Do some stuff for this button mode.finish(); return true; // Create a case for every item ... default: mode.finish(); return false; } } // Called when the user exits the action mode @Override public void onDestroyActionMode(ActionMode mode) { // This will clear the selection highlight and handlebars. // However, it only works in 4.4; I am still investigating // how to reliably clear the selection in 4.3 and earlier clearFocus(); } }

Una vez que esas piezas estén en su lugar, anule el método startActionMode para que la devolución de llamada ocurra en un clic largo:

public class CustomWebView extends WebView { @Override public ActionMode startActionMode(Callback callback) { ViewParent parent = getParent(); if (parent == null) { return null; } mActionModeCallback = new CustomActionModeCallback(); return parent.startActionModeForChild(this, mActionModeCallback); } }

Ahora tiene un menú personalizado que aparecerá y se rellenará cuando un usuario haga clic en su WebView . Para referencia, encontré esta información de un tutorial para desarrolladores de Android y modifiqué la sugerencia de esta respuesta .

Una nota final: esta técnica anula el menú nativo de copiar / pegar para el texto seleccionado. Si desea mantener esa funcionalidad, deberá implementarla usted mismo. (Es por eso que mi primer botón es ''copiar''). Si lo necesita, consulte este tutorial de Google para obtener más información y la forma correcta de implementarlo.


Para deshabilitar su selección de texto desde webview intente esto,

webView.setWebChromeClient(new WebChromeClient(){ [.... other overrides....] // @Override // https://bugzilla.wikimedia.org/show_bug.cgi?id=31484 // If you DO NOT want to start selection by long click, // the remove this function // (All this is undocumented stuff...) public void onSelectionStart(WebView view) { // By default we cancel the selection again, thus disabling // text selection unless the chrome client supports it. // view.notifySelectDialogDismissed(); } });


Podría sugerir una solución para esto. Puede usar setOnTouchListener y luego implementar la pulsación larga usted mismo.

onTouch -- case MotionEvent.ACTION_DOWN: mHanlder.removeCallbacks(startActionBar); mHandler.postDelayed(startActionBar,1000);

De esta manera usted podría lograr la misma acción.


Puede usar setOnTouchListener () para una pulsación larga / corta. y devuelva verdadero para que no suceda nada, anulando así la función de selección de texto predeterminada.


También puede intentar anular View.performLongClick (), que es responsable de llamar a View.onLongPress (). También puede intentar subir a los eventos de prensa prolongada de la vista principal. O hasta llegar a Window.Callback para su actividad (a través de Activity.getWindow (). Get / setCallback ()).

Me pregunto si existen otras formas para que aparezca el menú contextual de selección estándar además del evento de pulsación larga, por ejemplo, tal vez con un trackball o un teclado de hardware.


Use setOnTouchListener () implementa una pulsación larga


por alguna razón, el KeyEvent down & up no funciona en API LEVEL 16+ (Android 4.1+ JELLY_BEAN). No dispara el loadUrl del WebView. Así que tuve que reemplazar el dispatchKeyEvent con dispatchTouchEvent. Aquí está el código:

... MotionEvent touchDown = MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_DOWN, touchX, touchY, 0); webView.dispatchTouchEvent(touchDown); touchDown.recycle(); MotionEvent touchUp = MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_UP, touchX, touchY, 0); webView.dispatchTouchEvent(touchUp); touchUp.recycle(); String url = mUrl; ...

intentalo..