3

我有一个严重依赖 WebViews 的应用程序。在 KitKat 更新后,用户报告该应用程序在放大或缩小后不再重排文本。我查看了文档,发现发生了很多变化,但是虽然它谈到了很多关于缩放和缩放的内容,但没有提到任何关于文本重排的内容。似乎一旦设置了视口,缩放就是平移和缩放的事情,缩放后不再有文本重排的选项。有什么解决办法吗?

4

6 回答 6

10

KitKat Chromium WebView 不会重排文本。如果您担心文本易读性,请参阅迁移指南中的“NARROW_COLUMNS 和 SINGLE_COLUMN 不再支持”部分,其中建议的解决方案是使用文本自动调整大小。

如果您真的想恢复这种效果,那么您需要执行以下操作:

  1. 把你所有的内容放在一个<div id="contentRoot"> </div>
  2. 实施 onScaleChanged

    class MyWebViewClient extends WebViewClient {
        boolean scaleChangedRunnablePending = false;
    
        // Other code here
    
        @Override
        void onScaleChanged(final WebView webView, fload oldScale, float newScale) {
            if (scaleChangedRunnablePending) return;
            view.postDelayed(new Runnable() {
                @Override
                public void run() {
                    webView.evaluateJavaScript("recalculateWidth();", null);
                    scaleChangedRunnablePending = false;
                }
            }, 100);
        }
    }
    
    // Don't forget to webView.setWebViewClient(new MyWebViewClient());
    
  3. 使用以下 JavaScript

    function recalculateWidth() {
        $("#contentRoot").width(window.innerWidth);
    }
    

    或者,您也可以尝试修改视口元标记。

以上应该稍微延迟执行回流(这是为了将不必要的重新布局的数量降至最低)。

于 2013-11-15T11:35:16.527 回答
5

谢谢大家,为这个伟大的线程!我想加我的 2cents。无需在 HTML 文件中添加 id='contentRoot' 的额外 div。您可以使用必须已经存在于任何 html 中的body标签。此外,正如 EladAvron 所写,JS 代码可以直接从 Java 调用。总而言之,marcin.kosiba 发布的原始答案适用于您无权修改的 HTML。

对我有用的 JS 调用是:

webview.loadUrl("javascript:document.getElementsByTagName('body')[0].style.width=window.innerWidth+'px';");

我不知道为什么,但添加“px”对我来说至关重要。

于 2014-01-11T16:51:36.073 回答
2

此代码将确保 100% 解决您 的问题 KitKat 的问题以细头的形式出现

<meta name="viewport" content="maximum-scale=0"> java> view.evaluateJavascript("document.getElementsByTagName('head')[0].appendChild('<meta name=\"viewport\" content=\"maximum-scale=0\">');", null);

webView.setWebViewClient(new WebViewClient() {
            boolean scaleChangedRunnablePending = false;
            @Override
            public void onScaleChanged(final WebView view, float oldScale, float newScale) {
                super.onScaleChanged(view, oldScale, newScale);
                if (scaleChangedRunnablePending) return;
                view.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        view.evaluateJavascript("document.getElementsByTagName('head')[0].appendChild('<meta name=\"viewport\" content=\"maximum-scale=0\">');", null);
                        scaleChangedRunnablePending = false;
                    }
                }, 100);
            }
于 2015-04-08T06:19:43.633 回答
1

这是一个旧线程,但我只是想添加我正在使用的解决方案,以防有人从中受益。当页面完全缩小时,我在某些页面上遇到了奇怪的缩放问题,不幸的是,如果页面完全缩小,很难在 JavaScript 中检测到。解决这个问题的方法是在调整页面大小之前检测比例变化是否足够大。

以下解决方案适用于 KitKat 和 Lollipop,并且没有我在某些网站上看到的烦人的逐渐缩小。

class MyWebViewClient extends WebViewClient {
    private boolean mIsRunning = false;
    private float mZoomScale = 0.0f;
    private static final String REFLOW_TEXT = "javascript:document.getElementsByTagName('body')[0].style.width=window.innerWidth+'px';"

    @Override
    public void onScaleChanged(final WebView view, final float oldScale, final float newScale) {
        if (view.isShown() && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            if (mIsRunning)    // Don't run if there's a resize runnable in the queue
                return;
            if (Math.abs(mZoomScale - newScale) > 0.01f) {    // This stops the gradual zoom
                mIsRunning = view.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        mZoomScale = newScale;
                        view.evaluateJavascript(REFLOW_TEXT, null);
                        mIsRunning = false;
                    }
                }, 100);
            }
        }
    }
}

感谢 marcin.kosiba 和 user3185518,我结合并修改了他们的解决方案来构建这个答案。

于 2015-04-03T12:50:37.410 回答
1

感谢这些提示 - 结合它们,我发现以下解决方法不需要 Java:

var innerWidth = 0;
var text_reflow = function () {
  if (window.innerWidth != innerWidth) {
    innerWidth = window.innerWidth;
    document.getElementsByTagName('body')[0].style.width = innerWidth+'px';
  }
};
text_reflow();
setInterval(text_reflow, 500);

除了使用轮询间隔,还可以这样做,例如,

window.onresize = text_reflow;
addListener(window, 'touchstart', function (e) { text_reflow(); });

不幸的是,似乎无法捕捉到实际的捏合缩放事件。

于 2014-09-03T06:02:18.200 回答
0

使用 Javascript 的答案window.innerWidth应该适用于 Android 4.4(将 Chrome 33 用于 WebViews),但不适用于某些较新版本的 Android。这是因为 Chrome 48 和 Chrome 61+window.innerWidth在您缩放时保持不变(请参阅Chrome 问题 571297),这会影响所有 Android 9 设备和部分 Android 5 到 8 设备,具体取决于用户接受了哪些 Android System WebView 更新。

Chrome 61+ 上的替代品是提供的Visual Viewport API ,因此现在应该更新使用window.visualViewport.width的答案以实现最大兼容性。window.innerWidth(window.visualViewport!=undefined?window.visualViewport.width:window.innerWidth)

于 2019-07-31T14:40:19.833 回答