web-dev-qa-db-ja.com

ズームの有効化/無効化Android WebView

WebSettingsにはズームに関連するいくつかのメソッドがあります。

  • WebSettings.setSupportZoom
  • WebSettings.setBuiltInZoomControls

一部のデバイスでは動作が異なることに気付きました。たとえば、Galaxy Sのズームへのピンチはデフォルトで有効になっていますが、LG P500では無効になっていますボタン)。

P500でsetBuiltInZoomControls(true)を呼び出すと、これらの両方のバリアント(マルチタッチとボタン)が機能します。

LG P500などのデバイスでマルチタッチズームを有効にし、ズームボタンを無効にする方法(また、HTCデバイスにも同じ問題があることを知っています)

更新:ここにソリューションのほぼ完全なコードがあります

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

このコードは、WebViewのonTouchEventオーバーライドメソッドにあります。

64
Evgeny Nacu

私はWebViewのソースコードを見てきましたが、あなたが求めていることを達成するエレガントな方法はないと結論付けました。

結局、WebViewをサブクラス化し、OnTouchEventをオーバーライドしました。 _ACTION_DOWN_のOnTouchEventで、MotionEvent.getPointerCount()を使用しているポインターの数を確認します。ポインターが複数ある場合はsetSupportZoom(true)を呼び出し、そうでない場合はsetSupportZoom(false)を呼び出します。次にsuper.OnTouchEvent().を呼び出します

これにより、スクロール時のズームが事実上無効になり(ズームコントロールが無効になります)、ユーザーがズームをピンチしようとしているときにズームが有効になります。良い方法ではありませんが、これまでのところうまくいきました。

getPointerCount()は2.1で導入されたため、1.6をサポートする場合は追加の作業が必要になることに注意してください。

37
gngr44

API> = 11では、次を使用できます。

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

SDKに従って:

public void setDisplayZoomControls (boolean enabled) 

以来:APIレベル11

画面上のズームボタンを使用するかどうかを設定します。ビルトインズームコントロールの有効化とオンスクリーンズームコントロールの無効化の組み合わせにより、ピンチがオンスクリーンコントロールなしで機能するようにズームできます。

110
yuttadhammo

Android顧客向けのアプリケーションで作業中に同じ問題が発生し、この制限を「ハッキング」することができました。

Android WebViewクラスのソースコードを見て、 updateZoomButtonsEnabled()- method を見つけました。これは ZoomButtonsController- object は、ブラウザの現在の縮尺に応じてズームコントロールを有効または無効にします。

ZoomButtonsController- instanceを返すメソッドを検索し、このインスタンスを返す getZoomButtonsController()- method を見つけました。

メソッドはpublicとして宣言されていますが、WebView- documentationには文書化されておらず、Eclipseもそれを見つけることができませんでした。そこで、私はそれについていくつかのリフレクションを試み、独自のWebView-サブクラスを作成して、コントロールをトリガーするonTouchEvent()- methodをオーバーライドしました。

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

不要なコンストラクタを削除して、おそらく例外に反応することができます。

これはハックして信頼性が低いように見えますが、APIレベル4(Android 1.6)に戻ります。


@ jayellosがコメントで指摘したように、プライベートgetZoomButtonsController()-メソッドはAndroid 4.0.4以降。

ただし、その必要はありません。 条件付き実行 を使用すると、APIレベル11+のデバイス上にいるかどうかを確認し、公開された機能を使用できます(@ Yuttadhammo回答を参照)コントロールを非表示にします。

正確にそれを行うために、上記のサンプルコードを更新しました。

29
Lukas Knuth

私はLukas Knuthのソリューションを少し修正しました:

1)ウェブビューをサブクラス化する必要はありません。

2)いくつかのAndroid 1.6デバイスで、存在しないメソッドを別のクラスに入れないと、コードはバイトコード検証中にクラッシュします

3)ユーザーがページを上下にスクロールしても、ズームコントロールは表示されます。ズームコントローラーコンテナーを可視性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には良い解決策がありますが、Android 4.0.4 on Samsung Galaxy SIIでは、ズームコントロールがまだ見えます。

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

の代わりに

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

改善された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

投稿したソリューションは、ユーザーがドラッグしたときにズームコントロールが表示されないように機能するようですが、ユーザーがズームをピンチしてズームコントロールが表示される場合があります。 WebViewがピンチズームを受け入れるには2つの方法があり、そのうち1つだけがコードに関係なくズームコントロールを表示することに気付きました。

ユーザーピンチズームとコントロールが表示されます。

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

ユーザーピンチズームとコントロールが表示されない:

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

ソリューションにさらに光を当てることはできますか?

1
Pete

このようなソリューションを探しているかもしれませんが、私はWebView内のスケーリングに問題がありましたので、最善の方法はwebViewのすべてを設定するJava.classにあります: my 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