activer / désactiver le zoom dans Android WebView

Il existe des 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 au zoom est activé par défaut, mais sur le LG P500, il est désactivé (et maintenant je ne sais pas comment activer le pincement UNIQUEMENT pour zoomer, mais masquer les boutons de zoom).

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

Comment activer le zoom multitouch et désactiver les boutons de zoom sur les appareils tels que le LG P500? (En outre, je sais que les mêmes problèmes sont sur les appareils HTC)

MISE À JOUR: Voici le 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 se trouve dans la méthode de WebView sur laquelle onTouchEvent .

J’ai regardé le code source de WebView et j’ai conclu qu’il n’y a pas de moyen élégant pour accomplir ce que vous demandez.

J’ai fini par sous- OnTouchEvent WebView et OnTouchEvent . Dans OnTouchEvent pour ACTION_DOWN , je vérifie le nombre de pointeurs utilisant 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 efficacement le zoom lors du défilement (désactivant ainsi les commandes de zoom) et activera le zoom lorsque l’utilisateur est sur le sharepoint pincer le zoom. Ce n’est pas une belle façon de le faire, mais cela a bien fonctionné pour moi jusqu’à présent.

Notez que getPointerCount() été introduit en 2.1, vous devrez donc faire des choses supplémentaires si vous supportez 1.6.

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 commandes de zoom intégrées activées et de commandes de zoom à l’écran désactivées permet au pincement de zoomer pour fonctionner sans les commandes à l’écran

Nous avons eu le même problème en travaillant sur une application Android pour un client et j’ai réussi à “pirater” cette ressortingction.

J’ai regardé le code source Android pour la classe WebView et updateZoomButtonsEnabled() repéré une updateZoomButtonsEnabled() qui fonctionnait avec un ZoomButtonsController ZoomButtonsController pour activer et désactiver les contrôles de zoom en fonction de l’échelle actuelle du navigateur.

J’ai cherché une méthode pour retourner le ZoomButtonsController -instance et trouvé la getZoomButtonsController() , qui a renvoyé cette instance.

Bien que la méthode soit déclarée public , elle n’est pas documentée dans la documentation WebView et Eclipse ne l’a pas non plus trouvée. J’ai donc réfléchi à cela et créé ma propre sous-classe WebView pour remplacer la 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, AtsortingbuteSet attrs, int defStyle) { super(context, attrs, defStyle); disableControls(); } public NoZoomControllWebView(Context context, AtsortingbuteSet 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 pourriez vouloir supprimer les constructeurs inutiles et réagir probablement sur les exceptions.

Bien que cela semble pirate et peu fiable, il retourne à l’API Level 4 (Android 1.6).


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

Cependant, il n’est pas nécessaire de le faire. En utilisant une exécution conditionnelle , nous pouvons vérifier si nous sums sur un périphérique avec API Level 11+ et utiliser la fonctionnalité exposée (voir la réponse de @Yuttadhammo ) pour masquer les contrôles.

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

J’ai un peu modifié 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 bytecode sur certains appareils Android 1.6 si vous ne mettez pas de méthodes non existantes dans des classes séparées

3) Les commandes de zoom continueront d’apparaître 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 la 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); } 

Lukas Knuth a une bonne solution, mais sur Android 4.0.4 sur Samsung Galaxy SII, je regarde toujours les commandes de zoom. Et je le résout 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); } 

La solution que vous avez publiée semble fonctionner pour empêcher les contrôles de zoom d’apparaître lorsque l’utilisateur traîne, mais il existe des situations où un utilisateur pince le zoom et les commandes de zoom apparaissent. J’ai remarqué qu’il y a deux façons pour la vue Web d’accepter le zoom par pincement et qu’une seule d’entre elles fait apparaître les contrôles de zoom malgré votre code:

Les zooms et les contrôles de pincement 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 et les contrôles de pincement 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?

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, AtsortingbuteSet attrs) { super(context, attrs); init(); } public TweakedWebView(Context context, AtsortingbuteSet 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; } } 

hé là pour quiconque pourrait être à la recherche d’une solution comme celle-ci .. j’avais un problème avec la mise à l’échelle dans WebView, donc la meilleure façon de faire est dans votre java.class où vous définissez tout pour webView mettre ces deux lignes de code: (webViewSearch est le nom de mon webView -> webViewSearch = (WebView) findViewById (R.id.id_webview_search);)

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