我有一个严重依赖WebView的应用程序。 在KitKat更新后,用户报告该应用在放大或缩小后不再重排文本。 我查看了文档并发现很多内容已经发生了变化,但是虽然它有很多关于缩放和缩放的内容,但没有任何关于文本重排的内容。似乎一旦设置了视口,缩放就是一个全缩放的东西,并且不再有选项可以在缩放后重新进行文本重排。 有没有解决方案呢?
答案 0 :(得分:10)
KitKat Chromium WebView不会重排文本。如果您担心文本易读性,请参阅migration guide中的“NARROW_COLUMNS和SINGLE_COLUMN不再支持”部分,其中建议的解决方案是使用文本自动调整。
如果你真的想要带回这个效果那么你需要做这样的事情:
<div id="contentRoot"> </div>
实施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());
使用以下JavaScript
function recalculateWidth() {
$("#contentRoot").width(window.innerWidth);
}
或者,您也可以尝试修改视口元标记。
以上应该稍微延迟执行回流(这是为了将不必要的重新布局数量降至最低)。
答案 1 :(得分:5)
谢谢大家,为这个伟大的线程!!我想加我的2cents。 无需在HTML文件中添加id ='contentRoot'的额外div。您可以使用 body 标记,该标记必须已存在于任何html中。另外,正如EladAvron所写,JS代码可以直接从Java调用。总而言之,marcin.kosiba发布的原始答案适用于您无权修改的HTML。
对我有用的JS调用是:
webview.loadUrl("javascript:document.getElementsByTagName('body')[0].style.width=window.innerWidth+'px';");
我不知道为什么,但添加'px'对我来说至关重要。
答案 2 :(得分: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(); });
不幸的是,似乎无法捕捉到实际的缩放到缩放事件。
答案 3 :(得分: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,他们将我的解决方案结合起来并进行了修改以构建这个答案。
答案 4 :(得分:0)
此代码将确保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);
}
答案 5 :(得分:0)
使用JavaScript中的window.innerWidth
的答案应在Android 4.4(适用于WebView的Chrome 33)上运行,但不适用于某些较新的Android版本。这是因为Chrome 48和Chrome 61+缩放时window.innerWidth
保持不变(请参见Chrome issue 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)
,以实现最大的兼容性。