有没有一种方法可以在webview中禁用输入字段的缩放功能?

11
用户在输入框或文本区域中点击时,应用程序会进行缩放。 有没有简单的方法来禁用它?
目前有以下meta标签:
meta name="viewport" content="width=device-width; height=device-height; initial-scale=1.0; maximum-scale=1.0; user-scalable=no; target-densityDpi=device-dpi;"

一切看起来都很好,直到我在使用Android 2.2的设备上查看它,尤其是HTC Evo 4G


你想要在 WebView 中完全禁用缩放吗? - Quintin Robinson
我知道已经有一段时间了,但是你最终解决了这个问题吗?TheisEgeberg的答案有效吗? - mdelolmo
这真是疯狂,这不起作用。老实说,如果 viewport meta 标签的实现根据文档正确,我们应该只需要声明一个宽度就可以解决这个问题了。但是它根本不起作用,我们不得不采取临时措施来解决这些设备上的缩放问题,这又破坏了我们防止键盘缩放的能力! - Rick Kukiela
在我的Android 4.4.4设备上,上面的视口元标记成功地禁用了缩放。根据Android文档,元标记是首选方法:http://developer.android.com/reference/android/webkit/WebSettings.html#setDefaultZoom(android.webkit.WebSettings.ZoomDensity) - mbonness
10个回答

3

我经常处理这个问题。

你需要为不同的屏幕尺寸和手机准备不同的解决方案,这些方案需要在服务器端完成。

例如,这适用于HTC Desire:

<meta content='True' name='HandheldFriendly' />
<meta content='width=640px; initial-scale=0.50; maximum-scale=0.50;minimum-scale=0.50;' name='viewport' />
<meta name="viewport" content="width=640px" />

这是针对iPhone的:

<meta name="viewport" content="width=640px,user-scalable=0" />

1
在HTC代码示例中,为什么您在第二行将宽度设置为640像素,然后在第三行再次将其设置为相同的值? - matt lohkamp

2
webView.getSettings().setDefaultZoom(WebSettings.ZoomDensity.MEDIUM); 

此方法在API 19级中已被弃用。

这在最新的Android版本4.4.2中有效。

webView.setInitialScale(0);//default,no zoom
webView.getSettings().setSupportZoom(true);
webView.getSettings().setBuiltInZoomControls(true);
webView.getSettings().setLoadWithOverviewMode(false);
webView.getSettings().setUseWideViewPort(false);
webView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);

1

我找到了答案,至少对我有效。它适用于HTC Desire和三星3低分辨率。

  • 从HTML中删除viewport meta标签。

  • 在Java中应用可以在这里找到的解决方案。

    this.appView.getSettings().setSupportZoom( true ); //修改此处
    this.appView.getSettings().setDefaultZoom(WebSettings.ZoomDensity.FAR);//添加此行
    

    记得测试WebSettings.ZoomDensity.FAR是否适用于您的SDK版本(7及以上)。


1

这不仅仅是一个文本大小调整问题吗?

body{ 
    -webkit-text-size-adjust:none; 
}

1

Just set in manifest:

android:windowSoftInputMode="adjustPan"

这个可以禁用缩放,但是webview不会滚动以显示文本字段。 - Nicholas Ng

0
在 WebViewClassic.java 中,如果实际缩放比例小于默认缩放比例,则 displaySoftKeyboard 会缩放并移动。在 WebWiew.class 中有一个字段 mDefaultScale,源代码显示当你显示软键盘时,mActualScale 会改变。

因此,确保 mActualScale >= mDefaultScale 可以防止平移和重新缩放。(下面是从 grepcode 网站获取的 WebView.java 源代码--该网站已经不再运行。)

private void  displaySoftKeyboard(boolean isTextView) {
     InputMethodManager imm = (InputMethodManager)
     getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
        if (isTextView) {
            if (mWebTextView == null) return;
            imm.showSoftInput(mWebTextView, 0);

            if (mActualScale < mDefaultScale) {

                // bring it back to the default scale so that user can enter

                // text.
                mInZoomOverview = false;
                mZoomCenterX = mLastTouchX;
                mZoomCenterY = mLastTouchY;
                // do not change text wrap scale so that there is no reflow
                setNewZoomScale(mDefaultScale, false, false);
                adjustTextView(false);
            }
        }

        else { // used by plugins
            imm.showSoftInput(this, 0);
        }

    }

来自 frameworks/base/core/java/android/webkit/WebViewClassic.java 的 googleSource--WebViewClassic.java 代码(适用于JellyBean api 17)展示了类似的功能:

/**
 * Called in response to a message from webkit telling us that the soft
 * keyboard should be launched.
 */
private void displaySoftKeyboard(boolean isTextView) {
    InputMethodManager imm = (InputMethodManager)
            mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
    // bring it back to the default level scale so that user can enter text
    boolean zoom = mZoomManager.getScale() < mZoomManager.getDefaultScale();
    if (zoom) {
        mZoomManager.setZoomCenter(mLastTouchX, mLastTouchY);
        mZoomManager.setZoomScale(mZoomManager.getDefaultScale(), false);
    }
    // Used by plugins and contentEditable.
    // Also used if the navigation cache is out of date, and
    // does not recognize that a textfield is in focus.  In that
    // case, use WebView as the targeted view.
    // see http://b/issue?id=2457459
    imm.showSoftInput(mWebView, 0);
}

你能详细说明一下吗?这是来自操作系统的源代码吗?我们在这里是否有什么可以做来解决我们的问题,还是只是一种“这就是问题所在和原因,但你无法对其进行任何处理”的情况? - Rick Kukiela

0

这是我的解决方案:

在我所有的页面上,我都有:

<link rel="stylesheet" media="screen and (-webkit-device-pixel-ratio:0.75)" href="css/ldpi.css" />
<link rel="stylesheet" media="screen and (-webkit-device-pixel-ratio:1)" href="css/mdpi.css" />
<link rel="stylesheet" media="screen and (-webkit-device-pixel-ratio:1.5)" href="css/hdpi.css" />
<meta name="viewport" content="target-densitydpi=device-dpi" />

在带有输入字段的页面上,我有:
<link rel="stylesheet" media="screen" href="css/mdpi.css" />
<meta name="viewport" content="target-densitydpi=medium-dpi" />

所以,我在表单上没有从hdpi中受益,但至少它不会放大


0

终于,我找到了一个适用于我的实际项目的解决方案。

- MainActivity.java

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    WebView mWebView = (WebView) findViewById(R.id.webview);
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
        mWebView.setOnFocusChangeListener(new MyOnFocusChangeListener(getScale()));
    }
    Log.i(MainActivity.class.getSimpleName(), "getScale: " + getScale());
}

/**
 * Calculate the scale that we need to use manually.
 *
 * @return the scale that we need
 */
private float getScale() {
    DisplayMetrics display = this.getResources().getDisplayMetrics();
    int width = display.widthPixels;
    Float val = Float.valueOf(width) / Float.valueOf(Constants.PAGE_WIDTH);
    return val.floatValue();
}

- MyOnFocusChangeListener.java

public class MyOnFocusChangeListener implements View.OnFocusChangeListener {

    protected float mScale;

    public MyOnFocusChangeListener(float scale) {
        mScale = scale;
    }

    /**
     * Implement this method because we want to apply scale when focus changed.
     * @param v the View we want to apply scale when focus changed.
     * @param hasFocus has a focus or not.
     */
    public void onFocusChange(View v, boolean hasFocus) {
        if (hasFocus) {
            // We must try all cases because mDefaultScale will change on different versions of Android.
            try {
                Field defaultScale = WebView.class.getDeclaredField("mDefaultScale");
                defaultScale.setAccessible(true);
                defaultScale.setFloat(v, mScale);
            } catch (SecurityException e) {
                e.printStackTrace();
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (NoSuchFieldException e) {
                try {
                    Field zoomManager;
                    zoomManager = WebView.class.getDeclaredField("mZoomManager");
                    zoomManager.setAccessible(true);
                    Object zoomValue = zoomManager.get(v);
                    Field defaultScale = zoomManager.getType().getDeclaredField("mDefaultScale");
                    defaultScale.setAccessible(true);
                    defaultScale.setFloat(zoomValue, mScale);
                } catch (SecurityException e1) {
                    e1.printStackTrace();
                } catch (IllegalArgumentException e1) {
                    e.printStackTrace();
                } catch (IllegalAccessException e1) {
                    e.printStackTrace();
                } catch (NoSuchFieldException e1) {
                    try {
                        Field mProviderField = WebView.class.getDeclaredField("mProvider");
                        mProviderField.setAccessible(true);
                        Object webviewclassic = mProviderField.get(v);
                        Field zoomManager = webviewclassic.getClass().getDeclaredField("mZoomManager");
                        zoomManager.setAccessible(true);
                        Object zoomValue = zoomManager.get(webviewclassic);
                        Field defaultScale = zoomManager.getType().getDeclaredField("mDefaultScale");
                        defaultScale.setAccessible(true);
                        defaultScale.setFloat(zoomValue, mScale);
                    } catch (Exception e2) {
                        e2.printStackTrace();
                    }
                }
            }
        }
    }
}

添加一些关于类的额外信息。 - Pramod S. Nikam

0

我也遇到了同样的问题(在HTC Incredible上),但还没有找到一个好的解决方法。但是,我注意到如果你使用Google移动站点(http://google.com/m),你就不会出现这种情况,我正在努力弄清楚为什么会这样。

我尝试了stackoverflow上提到的所有修复方法,包括在这个线程中提到的,但是我找到的没有一种方法能够解决这个问题。

我发现的一个可行的但很烂的解决方法是将初始缩放比例设置为150(1.5倍),然后相应地缩放您的网站,那么您也不会出现这种缩放行为 - 可能是因为当您单击文本输入时它想要一个1.5倍的缩放级别,如果您已经处于该缩放级别,则不会发生任何事情?但是,这感觉非常hacky,并且可能不适用于所有手机。


0

我知道这个帖子已经是古老的历史了,但我也遇到了虚拟键盘的缩放问题,最终在这个链接中找到了解决方案:

http://rickluna.com/wp/2012/02/set-app-scaling-in-phonegap-android/

将以下代码添加到应用程序的Java源文件中:
appView.getSettings().setSupportZoom(false);
appView.getSettings().setUseWideViewPort(false);
WebSettings ws = appView.getSettings();
ws.setDefaultZoom(WebSettings.ZoomDensity.MEDIUM);
appView.getSettings().setDefaultZoom(WebSettings.ZoomDensity.MEDIUM);
appView.setInitialScale(0);
ws.setSupportZoom(false);
ws.setBuiltInZoomControls(false);
ws.setUseWideViewPort(false);

我将MEDIUM更改为FAR,这将保持屏幕在原始的1.0倍放大。

希望这能节省其他人一些搜索时间。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接