在Android WebView中启用/禁用放大

时间:2011-02-26 08:23:47

标签: android android-webview zoom multi-touch

WebSettings中有一些与缩放相关的方法:

  • WebSettings.setSupportZoom
  • WebSettings.setBuiltInZoomControls

我注意到它们在某些设备上的工作方式不同。 例如,在我的Galaxy S上,默认情况下启用缩放功能,但在LG P500上它被禁用(现在我不知道如何启用仅限缩放,但隐藏缩放按钮)。

当我拨打setBuiltInZoomControls(true)时,在P500上我得到这两个变体(多点触控和按钮)。

如何在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;
        }
    }

此代码位于我的onTouchEvent重写的WebView方法中。

8 个答案:

答案 0 :(得分:109)

在API> = 11上,您可以使用:

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

根据SDK:

public void setDisplayZoomControls (boolean enabled) 
  

自:API级别   11

     

设置是否使用屏幕上的缩放按钮。结合的   内置缩放控件已启用,屏幕缩放控件已禁用   允许在没有屏幕控制的情况下进行缩放以进行缩放

答案 1 :(得分:37)

我查看了WebView的源代码,并得出结论认为没有优雅的方法来完成你的要求。

我最终做的是继承WebView并覆盖OnTouchEvent。 在OnTouchEvent ACTION_DOWN中,我使用MotionEvent.getPointerCount()检查有多少指针。 如果有多个指针,我会调用setSupportZoom(true),否则我会调用setSupportZoom(false)。然后我调用super.OnTouchEvent().

这将在滚动时有效禁用缩放(从而禁用缩放控件),并在用户即将缩放时启用缩放。这不是一个好方法,但到目前为止它对我来说效果很好。

请注意,getPointerCount()是在2.1中引入的,所以如果你支持1.6,你将不得不做一些额外的事情。

答案 2 :(得分:29)

我们在为客户处理Android应用程序时遇到了同样的问题,我设法“破解”了这个限制。

我查看了WebView类的Android源代码,并发现updateZoomButtonsEnabled()-method正在使用ZoomButtonsController-object来启用和禁用缩放控件,具体取决于浏览器的当前比例。

我搜索了一个返回ZoomButtonsController - 实例的方法,并找到了返回此实例的getZoomButtonsController()-method

虽然该方法已声明为public,但未在WebView - 文档中记录,Eclipse也找不到它。所以,我尝试了一些反思并创建了我自己的WebView - 子类来覆盖触发控件的onTouchEvent() - 方法。

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 Level 4(Android 1.6)。


正如 @jayellos 在评论中指出的那样,私有getZoomButtonsController() - 方法已不再存在于Android 4.0.4及更高版本中。

但是,它不需要。使用conditional execution,我们可以检查我们是否在具有API级别11+的设备上并使用公开的功能(请参阅 @Yyadhammo 答案)来隐藏控件。

我更新了上面的示例代码,以便做到这一点。

答案 3 :(得分:10)

Ive modifiet Lukas Knuth的解决方案:

1)没有必要继承webview,

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

答案 4 :(得分:7)

Lukas Knuth有很好的解决方案,但在三星Galaxy SII的Android 4.0.4上,我仍然看起来变焦控制。我通过

解决了这个问题
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);
}

答案 5 :(得分:1)

您发布的解决方案似乎可以阻止缩放控件在用户拖动时显示,但是在某些情况下用户会捏缩放并且会出现缩放控件。我注意到webview有两种方式可以接受缩放缩放,只有其中一种方法会导致缩放控件出现,尽管你的代码是:

用户缩放缩放和控件出现:

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

您能否更好地了解您的解决方案?

答案 6 :(得分:1)

改进了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;
    }

}

答案 7 :(得分:0)

对于那些可能正在寻找像这样的解决方案的人来说嘿。我在WebView中有扩展的问题所以最好的方法是在你的java.class中为webView设置所有这两行代码:(webViewSearch是我的webView的名称 - > webViewSearch =(WebView)findViewById(R.id.id_webview_search);)

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