Comment remplacer le texte par défaut de sélection de webview android os 4.1+?

Avant de poster cette question que j'ai beaucoup cherché mais n'a pas pu trouver de réponse claire sur cette question.

J'ai remplacer le texte par défaut de sélection de webview android & afficher mon texte personnalisé de sélection de la boîte de dialogue options. J'ai essayé cet exemple de code projet.

Cet exemple de projet de travaux sur les appareils suivants & émulateur :

  • Acer Iconia a500 tablet : 10 pouces : Android OS 3.0
  • Acer Iconia a500 tablet : 10 pouces : Android OS 3.2
  • Samsung Galaxy Tab : 10 pouces : Android OS 4.0
  • Samsung Galaxy Tab : 7 pouces : Android OS 4.0
  • Émulateur : Peau-WVGA800 : Android OS 4.1.2

Ne fonctionne pas sur les appareils suivants :

  • Samsung Galaxy Tab : 10 pouces : Android OS 4.1.2
  • Samsung Galaxy Tab : 7 pouces : Android OS 4.1.2

Sur le système d'exploitation android version 4.1 & 4.1+ au lieu d'afficher mon texte personnalisé option de sélection de la boîte de dialogue, il montre android par défaut du système de la barre d'action pour la sélection de texte.

J'ai beaucoup cherché sur ce, beaucoup ont suggéré d'utiliser onLongClick() méthode de la interface

J'ai déjà posé une question sur ce forum s'il vous plaît voir cette lien, avec des réponses à ces questions, je suis capable de cloner onLongClick() événement, mais je ne peux pas arrêter de texte par défaut de sélection de la barre d'action.

Pour ce scénario, j'ai quelques questions.

1.Pourquoi onLongClick() la méthode des arrêts de travail pour le dispositif en cours d'exécution sur le système d'exploitation android version 4.1+ ?

2.Comment arrêter de texte par défaut de sélection de la barre d'action sur le long appuyant sur le texte de webview ?

C'est ma coutume webview classe.

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

}

Merci D'Avance!

  • Pouvez-vous s'il vous plaît poster comment vous avez mis en œuvre onLongClick()? Sur mon GalaxyS3 (OS 4.1.2), il fonctionne sans problème et j'ai réussi a changé donc je ne suis pas en montrant le mode d'action.
  • J'ai édité ma question avec plus de la coutume webview code, ce code est à la fois onLongClick méthode ainsi que le clone de onLongClick à l'aide de longClickRunnable, longClickHandler, le reste du code & classes de support pour Drag & Drop sont même exemple de projet à partir de github.com/btate/BTAndroidWebViewSelection
  • J'ai testé le même code sur GalaxyS3 OS 4.1.2 il fonctionne bien, la prévention de webview du texte de sélection de mode & montrant par défaut de mon texte personnalisé options de sélection, mais le même code ne fonctionne pas sur Tablette Samsung 10 pouces avec OS 4.1.2
  • Essayez d'enquêter sur les API de WebView en cours d'exécution en utilisant la réflexion. Tablettes Samsung a peu différent WebView mise en œuvre. Il y avait quelques méthodes qui peuvent vous aider. Je ne me souviens pas exacte des noms ou des signatures, je vais essayer de le faire plus tard.
  • Salut, Sachin je suis face à un même problème lors de la mise en œuvre de richtexteditor à l'aide de webview. Je me demandais u ne trouver aucune solution de contournement pour ce....merci
  • J'ai dû faire quelque chose de similaire, c'est comment je l'ai réalisé. stackoverflow.com/a/21626675/3248932

InformationsquelleAutor sachin003 | 2013-06-10