【问题标题】:enable/disable zoom in Android WebView在 Android WebView 中启用/禁用缩放
【发布时间】:2011-07-04 19:04:08
【问题描述】:

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 重写方法中。

【问题讨论】:

  • 我也遇到了同样的问题.. multiTouchZoom 和buttonsZoom 变量是什么?
  • @Luizje 我知道这是旧的,但万一其他人发现它:将 getPointerCount(ev) 更改为 ev.getPointerCount() 它将起作用!
  • 我不确定是否有人需要这个,但看看我的“hack around”。它可以回溯到 Android 1.6
  • @Evgeny 什么是 multiTouchZoom 和 buttonsZoom 变量?您是如何获得缩放按钮和多点触控缩放的事件的?如果你不介意,你能把完整的代码贴在这里吗?

标签: android android-webview zooming multi-touch


【解决方案1】:

嘿,对于任何可能正在寻找这样的解决方案的人。我在 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);

【讨论】:

  • 这像桌面模式吗?
  • hm,因为webView是展示网页的视图,这两个定义为: setLoadWithOverviewMode(boolean overview) 设置WebView是否以概览模式加载页面,即缩小内容到按宽度适合屏幕,并且 setUseWideViewPort(boolean use) 设置 WebView 是否应启用对“viewport”HTML 元标记的支持或应使用宽视口。你可以说这就像destkop模式^^
  • 我只是想知道第三方网络浏览器如何切换“桌面模式”。我不认为他们使用这个。我认为他们改变了用户代理或其他东西。
【解决方案2】:

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

}

【讨论】:

    【解决方案3】:

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

    我查看了 WebView 类的 Android 源代码,发现 updateZoomButtonsEnabled()-methodZoomButtonsController-object 一起使用,以根据浏览器的当前比例启用和禁用缩放控件。

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

    虽然该方法被声明为public,但它没有记录在WebView-documentation 中,Eclipse 也找不到它。因此,我对此进行了一些反思,并创建了自己的WebView-subclass 来覆盖触发控件的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 级别 4 (Android 1.6)。


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

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

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

    【讨论】:

    • @Lukas,它不适用于 Android 4.0.4。它返回 NoSuchMethodException: getZoomButtonsController.
    • @jayellos 在 Android 4 上,您可以使用 API 级别 11 提供的 WebSettings.setDisplayZoomControls(boolean) 方法。
    • @LukasKnuth 感谢您的帮助。现在它起作用了。我将目标 Api 级别更改为 11+。正如在条件执行时所说。在我的目标 Api 为 10 之前,我无法使用 .setDisplayZoomControls(boolean) 函数。再次感谢您。
    • 如果有人在缩放以在 API 11 之前的设备上工作时遇到问题,请移动 this.getSettings().setBuiltInZoomControls(true); 以在所有 WebView 上运行,而不仅仅是 API 11 或更高版本。 (仍然隐藏缩放控件。我还添加了this.getSettings().setUseWideViewPort(true); 用于双击缩放
    • if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.GINGERBREAD_MR1) { 如果您的最低 sdk 版本为 2.3.3(API 级别 10),请使用此选项跨度>
    【解决方案4】:

    我稍微修改了 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);
      }
    

    【讨论】:

    • 完美解决方案。我唯一要改变的是 invoke(webview, (Object[]) null)) 所以你不会在 Eclipse 中收到警告。
    • 看起来是个不错的解决方案。由于此错误,我无法编译:调用需要 API 级别 11(当前最小值为 8):android.webkit.WebSettings#setDisplayZoomControls
    • 按 Ctrl-1 选择@SuppressLint
    • @ropo 此方法仅隐藏缩放控件但不禁用这些按钮(在 API 级别 10 上,在 web 视图中,如果我触摸右下角则会缩小)。有什么解决方案可以解决那个问题? API 10 以上就可以了。
    【解决方案5】:

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

    【讨论】:

    • 我知道这个答案已经有几个月了,但我只想说声谢谢。这个答案与 Lukas Knuth 的结合是完美的。
    【解决方案6】:

    我查看了WebView 的源代码并得出结论,没有优雅的方法可以完成您的要求。

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

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

    请注意,getPointerCount() 是在 2.1 中引入的,因此如果您支持 1.6,则必须做一些额外的事情。

    【讨论】:

    • 感谢您的解决方案。它几乎按照我想要的方式工作。我将在问题中发布代码摘要
    • 我说过我爱你吗,gngr44?
    • 太棒了!非常感谢:)
    【解决方案7】:

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

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

    根据 SDK:

    public void setDisplayZoomControls (boolean enabled) 
    

    自:API 级别 11

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

    【讨论】:

    • 太糟糕了 60%+ 的用户仍在使用 pre-API 11...我是在您发布它一年后说的!您发布建议时的数字是什么样的?
    • 我将它与this answer 一起使用,以默认我的视图缩小并能够捏合缩放。我刚刚离开了显示部分来使用 pre-API 11
    • 好答案。还要确保元 中的另一个控制因素是“用户可扩展”
    【解决方案8】:

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

    用户捏缩放和控件出现:

    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
    

    您能否详细说明您的解决方案?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-28
      • 2014-01-23
      • 1970-01-01
      • 1970-01-01
      • 2017-10-28
      • 2012-05-07
      相关资源
      最近更新 更多