web-dev-qa-db-fra.com

Comment remplacer la sélection de texte par défaut de Android webview os 4.1+?

Avant de publier cette question, j'ai beaucoup cherché mais je n'ai pas trouvé de réponses claires à ce problème.

Je dois remplacer la sélection de texte par défaut de Android webview et afficher mes options de boîte de dialogue de sélection de texte personnalisé. J'ai essayé cet exemple de code projet .

Cet exemple de projet fonctionne sur les appareils et émulateurs suivants:

  • Tablette Acer Iconia a500: 10 pouces: Android OS - 3.0
  • Tablette Acer Iconia a500: 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: Skin-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 Android os version 4.1 et 4.1+ au lieu d'afficher ma boîte de dialogue d'option de sélection de texte personnalisée, il affiche Android pour la sélection de texte.

J'ai beaucoup cherché à ce sujet, 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 ceci lien , avec des réponses à ces questions, je suis capable de cloner l'événement onLongClick () mais je ne peux pas arrêter la barre d'action de sélection de texte par défaut.

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

1.Pourquoi la méthode onLongClick () cesse de fonctionner pour un appareil fonctionnant sur Android os version 4.1+?

2.Comment arrêter la barre d'action de sélection de texte par défaut en appuyant longuement sur le texte de la vue Web?

Ceci est ma classe de vue Web personnalisée.

  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!

45
sachin003

Je me rends compte que c'est une vieille question, mais il n'y a pas de réponse acceptée, et aucune des réponses fournies ne reçoit beaucoup de votes.

J'ai réalisé ce que vous essayez d'accomplir en créant un rappel de mode d'action personnalisé. Cela permet la création d'une barre d'actions contextuelle personnalisée (CAB) lorsque (dans le cas d'un WebView) un utilisateur clique longuement sur la vue. REMARQUE: Cela ne fonctionne que dans 4.0+ et une seule pièce ne fonctionne que dans 4.4.

Créez un nouveau fichier Android XML contenant la mise en page de votre menu personnalisé. Voici le mien (context_menu.xml) à titre d'exemple:

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

Maintenant que le menu est défini, créez un rappel pour celui-ci:

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

Une fois ces éléments en place, remplacez la méthode startActionMode afin que le rappel se produise réellement sur un clic long:

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

Vous avez maintenant un menu personnalisé qui apparaîtra et se remplira lorsqu'un utilisateur clique longuement sur votre WebView. Pour référence, j'ai trouvé ces informations à partir d'un tutoriel pour les développeurs Android et j'ai modifié la suggestion de cette réponse .

Une dernière remarque: cette technique remplace le menu natif copier/coller pour le texte sélectionné. Si vous souhaitez conserver cette fonctionnalité, vous devrez la mettre en œuvre vous-même. (C'est pourquoi mon premier bouton est "copier".) Si vous en avez besoin, reportez-vous à ce tutoriel Google pour plus d'informations et la bonne façon de l'implémenter.

4
Sean Beach

Utilisez le setOnTouchListener () pour un appui long/court long. et renvoie true pour que rien ne se passe, remplaçant ainsi la fonction de sélection de texte par défaut.

2
user2783434

J'ai pu résoudre ce problème. J'étais également confronté à ce problème et je n'ai trouvé aucune solution sur le Web.

Ainsi, si vous configurez un écouteur LongClick, la vue Web cesserait du tout d'afficher la sélection. Après avoir approfondi le code Webview, j'ai trouvé qu'il appelait la méthode startRunMode de WebView et lui passait une instance de la classe SelectActionCallbackMode.

J'ai simplement étendu la classe Webview et remplacé la méthode startRunMode comme ceci:

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

Cela a forcé Webview à afficher mon rappel au lieu d'afficher celui par défaut de Webview. Cela garantissait que la sélection fonctionnait aussi bien qu'auparavant et que mon CAB était affiché chaque fois que la sélection était faite. La seule mise en garde était que je devais écrire du code pour renvoyer moi-même le CAB.

Testé sur les appareils 4.1, 4.2 et 4.3.

J'espère que cela t'aides.

1
Pulkit Gupta

Je pourrais suggérer une solution de contournement pour cela. Vous pouvez utiliser setOnTouchListener puis implémenter vous-même la pression longue.

onTouch --

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

De cette façon, vous pourriez réaliser la même action.

0
blganesh101

Pour désactiver votre sélection de texte à partir de la vue Web, essayez ceci,

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
Khunt Nirav

Utilisez setOnTouchListener () pour implémenter un appui long

0
shivaprakash

au cas où quelqu'un essaie simplement de supprimer la sélection de texte par défaut, j'ai eu le même problème sur un Samsung Galaxy Tab sur Android 4.1.2 et j'ai fini par écrire mon propre 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;
  }

}

et le référencer dans mon xml:

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

Vous pouvez également essayer de remplacer View.performLongClick (), qui est responsable de l'appel de View.onLongPress (). Vous pouvez également essayer d'accéder aux événements de presse longue de la vue parent. Ou tout le chemin jusqu'à Window.Callback pour votre activité (via Activity.getWindow (). Get/setCallback ()).

Je me demande s'il existe d'autres façons pour le menu contextuel de sélection standard d'apparaître en plus de l'événement de pression longue, par exemple peut-être avec une boule de commande ou un clavier matériel.

0
Dane White

une raison quelconque pour laquelle KeyEvent down & up ne fonctionne pas dans API LEVEL 16+ (Android 4.1+ JELLY_BEAN). Il ne déclenche pas loadUrl de WebView. J'ai donc dû remplacer dispatchKeyEvent par dispatchTouchEvent. Voici le 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;
...

essayez-le ..

0
Khunt Nirav