How to override default text selection in os 4.1+ Android browser?

Before posting this question, I searched a lot, but could not find clear answers to this problem.

I need to override the default text selection in the android web browser and show the options for the custom text selection dialog. I tried this sample code project .

This sample project works on the following devices and emulator:

  • Acer Iconia a500 tablet: 10 inch: Android OS - 3.0
  • Acer Iconia a500 tablet: 10 inch: Android OS - 3.2
  • Samsung Galaxy Tab: 10 inches: Android OS - 4.0
  • Samsung Galaxy Tab: 7 inches: Android OS - 4.0
  • Emulator: Skin-WVGA800: Android OS - 4.1.2

Does not work on the following devices:

  • Samsung Galaxy Tab: 10 inches: Android OS - 4.1.2
  • Samsung Galaxy Tab: 7 inches: Android OS - 4.1.2

In android os versions 4.1 and 4.1+, instead of showing a dialog for selecting custom text, the default Android action bar for selecting text is displayed on the screen.

I searched a lot in this question, many suggested using the onLongClick () interface method

I already asked a question on this forum, see the link with answers to these questions. I can clone the onLongClick () event, but I cannot stop the default action bar for the text.

I have few questions for this scenario.

1. Why does the onLongClick () method stop working on a device running android os version 4.1+?

2.How to stop the default text selection bar by long clicking on the text from the web view?

This is my custom webview class.

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 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); } 

}

Thanks in advance!

+46
android textselection android-webview
Jun 10 '13 at 12:45
source share
9 answers

I understand that this is an old question, but there is no answer, and none of the answers provided has a large number of votes.

I achieved what you are trying to achieve by creating a custom action mode callback. This allows you to create a custom contextual action panel (CAB) when (in the case of WebView ) the user WebView long click on the view. NOTE: This only works in 4.0+, and one part only works in 4.4.

Create a new Android XML file containing the layout for your custom menu. Here is my (context_menu.xml) as an example:

 <?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> 

Now that the menu is defined, create a callback for it:

 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(); } } 

Once these parts are in place, override the startActionMode method startActionMode that the callback actually executes with a long click:

 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); } } 

Now you have a custom menu that will be displayed and populated when the user clicks on the WebView for a long time. For reference, I found this information from the Android Developer Tutorial and changed the offer of this answer .

One final note: this method overrides its own copy / paste menu for the selected text. If you want to keep this functionality, you will need to implement it yourself. (That’s why my first button is β€œcopy.”) If you need this, check out this Google tutorial for more information and the right way to implement it.

+4
Mar 21 '14 at 16:08
source share

Use setOnTouchListener () for long / short long press. and return true so that nothing happens, thereby overriding the default text selection function.

+2
Sep 16 '13 at 9:48 on
source share

I was able to solve this. I also ran into this problem and could not find a solution on the Internet.

So, if you configured the LongClick listener, Webview will stop showing the selection at all. After deep digging into Webview code, I found that it calls the WebView method startRunMode and passes an instance of the SelectActionCallbackMode class.

I simply extended the Webview class and redefined the startRunMode method as follows:

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

This forced Webview to display my callback instead of displaying Webview by default. This ensured that the selection worked as smoothly as before, and my CAB was displayed every time the selection was made. The only caveat was that I had to write code to let go of the SAB.

Tested on devices 4.1, 4.2 and 4.3.

Hope this helps.

+1
Feb 07 '14 at 11:39
source share

I could suggest a workaround for this. You can use setOnTouchListener and then implement a long press.

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

That way you can achieve the same aciton.

0
Jun 27 '13 at 7:26
source share

For some reason, KeyEvent down and up do not work in the LEVEL 16+ API (Android 4.1+ JELLY_BEAN). It does not start loading WebView loadUrl. So I had to replace dispatchKeyEvent dispatchTouchEvent. Here is the code:

 ... 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; ... 

try it.

0
Jul 16 '13 at 12:01
source share

To turn off text selection from web browsing, try this,

 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(); } }); 
0
Jul 16 '13 at 12:05
source share

You can also try overriding View.performLongClick (), which is responsible for calling View.onLongPress (). You can also try to approach the parent view of long events. Or all the way to Window.Callback for your activity (via Activity.getWindow (). Get / setCallback ()).

I am wondering if there are other options for the standard selection context menu besides the long-press event, for example, possibly with a trackball or a hardware keyboard.

0
Aug 21 '13 at 2:06 on
source share

if someone tries to just delete the default text selected, I had the same problem on the Samsung Galaxy Tab tab on Android 4.1.2, and in the end I wrote my own 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; } } 

and send it to my xml:

 <com...CustomWebView android:id="@+id/webview" android:layout_width="fill_parent" android:layout_height="fill_parent" /> 
0
Aug 29 '13 at 12:26
source share

Use setOnTouchListener () to implement a long press

0
Sep 14 '13 at 6:20
source share



All Articles