web-dev-qa-db-fra.com

activer / désactiver le zoom avant Android WebView

Il existe certaines méthodes dans WebSettings liées au zoom:

  • WebSettings.setSupportZoom
  • WebSettings.setBuiltInZoomControls

J'ai remarqué qu'ils fonctionnent différemment sur certains appareils. Par exemple, sur mon Galaxy S, le pincement pour zoomer est activé par défaut, mais sur LG P500, il est désactivé (Et maintenant, je ne sais pas comment activer le pincement UNIQUEMENT pour zoomer, mais le masquer boutons).

Sur P500, lorsque j'appelle setBuiltInZoomControls(true), ces deux variantes fonctionnent (multitouch et boutons).

Comment activer le zoom multitactile et désactiver les boutons de zoom sur des appareils tels qu'un LG P500? (Je sais également que les mêmes problèmes se posent sur les appareils HTC)

UPDATE: Voici un code presque complet pour la solution

if (ev.getAction() == MotionEvent.ACTION_DOWN ||
        ev.getAction() == MotionEvent.ACTION_POINTER_DOWN ||
        ev.getAction() == MotionEvent.ACTION_POINTER_1_DOWN ||
        ev.getAction() == MotionEvent.ACTION_POINTER_2_DOWN ||
        ev.getAction() == MotionEvent.ACTION_POINTER_3_DOWN) {
    if (multiTouchZoom && !buttonsZoom) {
        if (getPointerCount(ev) > 1) {
            getSettings().setBuiltInZoomControls(true);
            getSettings().setSupportZoom(true);
        } else {
            getSettings().setBuiltInZoomControls(false);
            getSettings().setSupportZoom(false);
        }
    }
}

if (!multiTouchZoom && buttonsZoom) {
    if (getPointerCount(ev) > 1) {
        return true;
    }
}

Ce code est dans ma méthode onTouchEvent surchargée de WebView.

64
Evgeny Nacu

J'ai examiné le code source de WebView et j'ai conclu qu'il n'y avait pas de moyen élégant d'accomplir ce que vous demandiez.

Ce que j'ai fini par faire, c'est de sous-classer WebView et de remplacer OnTouchEvent. Dans OnTouchEvent pour ACTION_DOWN, Je vérifie combien de pointeurs utilisent MotionEvent.getPointerCount(). S'il y a plus d'un pointeur, j'appelle setSupportZoom(true), sinon j'appelle setSupportZoom(false). J'appelle alors le super.OnTouchEvent().

Cela désactivera effectivement le zoom lors du défilement (désactivant ainsi les commandes de zoom) et activera le zoom lorsque l'utilisateur est sur le point de pincer le zoom. Ce n'est pas une bonne façon de le faire, mais cela a bien fonctionné pour moi jusqu'à présent.

Notez que getPointerCount() a été introduit dans la version 2.1. Vous devrez donc faire des choses supplémentaires si vous supportez la version 1.6.

37
gngr44

Sur API> = 11, vous pouvez utiliser:

wv.getSettings().setBuiltInZoomControls(true);
wv.getSettings().setDisplayZoomControls(false);

Selon le SDK:

public void setDisplayZoomControls (boolean enabled) 

Depuis: API niveau 11

Définit si les boutons de zoom à l'écran sont utilisés. Une combinaison de contrôles de zoom intégrés activés et de contrôles de zoom à l'écran désactivés permet au zoom pincé de fonctionner sans les contrôles à l'écran

110
yuttadhammo

Nous avons eu le même problème lorsque nous travaillions sur une application Android pour un client) et que nous avons réussi à "pirater" cette restriction.

J'ai jeté un œil à la Android code source de la classe WebView et j'ai repéré une méthode updateZoomButtonsEnabled()-) qui fonctionnait avec un ZoomButtonsController- object pour activer et désactiver les commandes de zoom en fonction de l'échelle actuelle du navigateur.

J'ai cherché une méthode pour retourner l'instance ZoomButtonsController et j'ai trouvé la méthode getZoomButtonsController()- , qui a renvoyé cette instance même.

Bien que la méthode soit déclarée public, elle n’est pas documentée dans la documentation WebView- et Eclipse n’a pas non plus été trouvée. J'ai donc essayé de réfléchir à cela et créé ma propre sous-classe WebView- pour remplacer la méthode onTouchEvent()-, qui a déclenché les contrôles.

public class NoZoomControllWebView extends WebView {

    private ZoomButtonsController zoom_controll = null;

    public NoZoomControllWebView(Context context) {
        super(context);
        disableControls();
    }

    public NoZoomControllWebView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        disableControls();
    }

    public NoZoomControllWebView(Context context, AttributeSet attrs) {
        super(context, attrs);
        disableControls();
    }

    /**
     * Disable the controls
     */
    private void disableControls(){
        if (Android.os.Build.VERSION.SDK_INT >= Android.os.Build.VERSION_CODES.HONEYCOMB) {
            // Use the API 11+ calls to disable the controls
            this.getSettings().setBuiltInZoomControls(true);
            this.getSettings().setDisplayZoomControls(false);
        } else {
            // Use the reflection magic to make it work on earlier APIs
            getControlls();
        }
    }

    /**
     * This is where the magic happens :D
     */
    private void getControlls() {
        try {
            Class webview = Class.forName("Android.webkit.WebView");
            Method method = webview.getMethod("getZoomButtonsController");
            zoom_controll = (ZoomButtonsController) method.invoke(this, null);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        super.onTouchEvent(ev);
        if (zoom_controll != null){
            // Hide the controlls AFTER they where made visible by the default implementation.
            zoom_controll.setVisible(false);
        }
        return true;
    }
}

Vous voudrez peut-être supprimer les constructeurs inutiles et réagir probablement aux exceptions.

Bien que cela semble hacky et peu fiable, il fonctionne de nouveau à l'API de niveau 4 (Android 1.6).


Comme @ jayellos a souligné dans les commentaires, la méthode privée getZoomButtonsController()- n'existe plus sur Android 4.0.4 et versions ultérieures.

Cependant, ce n'est pas nécessaire. En utilisant exécution conditionnelle , nous pouvons vérifier si nous sommes sur un périphérique avec une API de niveau 11+ et utiliser la fonctionnalité exposée (voir @ Yuttadhammo répondre) pour masquer les contrôles.

J'ai mis à jour l'exemple de code ci-dessus pour faire exactement cela.

29
Lukas Knuth

Je modifie un peu la solution de Lukas Knuth:

1) Il n'est pas nécessaire de sous-classer la vue Web,

2) le code va planter lors de la vérification du bytecode sur certains Android 1.6 périphériques si vous ne mettez pas de méthodes non existantes dans des classes séparées)

3) Les commandes de zoom apparaissent toujours si l'utilisateur fait défiler une page vers le haut ou le bas. Je règle simplement le conteneur du contrôleur de zoom sur visibilité GONE

  wv.getSettings().setSupportZoom(true);
  wv.getSettings().setBuiltInZoomControls(true);
  if (Android.os.Build.VERSION.SDK_INT >= Android.os.Build.VERSION_CODES.HONEYCOMB) {
    // Use the API 11+ calls to disable the controls
    // Use a seperate class to obtain 1.6 compatibility
    new Runnable() {
      public void run() {
        wv.getSettings().setDisplayZoomControls(false);
      }
    }.run();
  } else {
    final ZoomButtonsController zoom_controll =
        (ZoomButtonsController) wv.getClass().getMethod("getZoomButtonsController").invoke(wv, null);
    zoom_controll.getContainer().setVisibility(View.GONE);
  }
10
Jacob Nordfalk

Lukas Knuth a une bonne solution, mais sur Android 4.0.4 sur le Samsung Galaxy SII, je regarde toujours les commandes de zoom. Et je le résous via

if (zoom_controll!=null && zoom_controll.getZoomControls()!=null)
{
   // Hide the controlls AFTER they where made visible by the default implementation.
   zoom_controll.getZoomControls().setVisibility(View.GONE);
}

au lieu de

if (zoom_controll != null){
   // Hide the controlls AFTER they where made visible by the default implementation.
   zoom_controll.setVisible(false);
}
7
Mihail M

Version améliorée de Lukas Knuth:

public class TweakedWebView extends WebView {

    private ZoomButtonsController zoomButtons;

    public TweakedWebView(Context context) {
        super(context);
        init();
    }

    public TweakedWebView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public TweakedWebView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    private void init() {
        getSettings().setBuiltInZoomControls(true);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
            getSettings().setDisplayZoomControls(false);
        } else {
            try {
                Method method = getClass()
                        .getMethod("getZoomButtonsController");
                zoomButtons = (ZoomButtonsController) method.invoke(this);
            } catch (Exception e) {
                // pass
            }
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        boolean result = super.onTouchEvent(ev);
        if (zoomButtons != null) {
            zoomButtons.setVisible(false);
            zoomButtons.getZoomControls().setVisibility(View.GONE);
        }
        return result;
    }

}
1
yanchenko

La solution que vous avez publiée semble fonctionner pour que les commandes de zoom ne s'affichent pas lorsque l'utilisateur glisse, mais il existe des situations dans lesquelles l'utilisateur pincera le zoom et les commandes de zoom s'afficheront. J'ai remarqué que la visualisation Web acceptait le zoom par pincement de deux manières. Seule l'une d'elles provoque l'affichage des commandes de zoom malgré votre code:

Les zooms et contrôles de pincement utilisateur apparaissent:

ACTION_DOWN
getSettings().setBuiltInZoomControls(false); getSettings().setSupportZoom(false);
ACTION_POINTER_2_DOWN
getSettings().setBuiltInZoomControls(true); getSettings().setSupportZoom(true);
ACTION_MOVE (Repeat several times, as the user moves their fingers)
ACTION_POINTER_2_UP
ACTION_UP

Le zoom de pincement et les commandes de l'utilisateur n'apparaissent pas:

ACTION_DOWN
getSettings().setBuiltInZoomControls(false); getSettings().setSupportZoom(false);
ACTION_POINTER_2_DOWN
getSettings().setBuiltInZoomControls(true); getSettings().setSupportZoom(true);
ACTION_MOVE (Repeat several times, as the user moves their fingers)
ACTION_POINTER_1_UP
ACTION_POINTER_UP
ACTION_UP

Pouvez-vous nous éclairer davantage sur votre solution?

1
Pete

hé là pour tous ceux qui cherchent une solution comme celle-ci .. J'ai eu un problème avec la mise à l'échelle dans WebView alors la meilleure façon de le faire est dans votre classe Java. où vous définissez tout pour webView, mettez cette ligne de code en deux: (webViewSearch est le nom de ma webView -> webViewSearch = (WebView) findViewById (R.id.id_webview_search);)

// force WebView to show content not zoomed---------------------------------------------------------
    webViewSearch.getSettings().setLoadWithOverviewMode(true);
    webViewSearch.getSettings().setUseWideViewPort(true);
0
Perhpethua