倒数第二,但也是最关键的一点:我在阅读WebView类的源代码时,发现了这个关于强制重绘的小注解。有一个static final boolean,当设置为true时,它将强制视图总是重绘。我对Java语法不是很精通,但我认为你不能直接更改类的静态final属性。所以我最终做的是这样扩展该类:
import org.apache.cordova.CordovaWebView;
import android.content.Context;
import android.graphics.Canvas;
public class MyWebView extends CordovaWebView {
public static final String TAG = "MyWebView";
public MyWebView(Context context) {
super(context);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// Warning! This will cause the WebView to continuously be redrawn
// and will drain the devices battery while the view is displayed!
invalidate();
}
}
public void init(){
CordovaWebView webView = new MyWebView(MainActivity.this);
super.init(webView, new CordovaWebViewClient(this, webView), new CordovaChromeClient(this, webView));
}
public void init(){
CordovaWebView webView = new MyWebView(MainActivity.this);
super.init(webView, new IceCreamCordovaWebViewClient(this, webView), new CordovaChromeClient(this, webView));
}
/**
* Due to bug in 4.2.2 sometimes the webView will not draw its contents after the data has loaded.
* Triggers redraw. Does not work in webView's onPageFinished callback for some reason
*/
private void forceWebViewRedraw()
{
mWebView.post(new Runnable() {
@Override
public void run()
{
mWebView.invalidate();
if(!isFinishing())
mWebView.postDelayed(this, 1000);
}
});
}
9条答案
按热度按时间xpszyzbs1#
备注:
Android 4.4+有一个更好的解决方案。它是一个称为 CrossWalk 的
WebView
替代品。它使用了最新的Chromium套件,非常棒。你可以在这里阅读它:crosswalk-project.org而且,自从Android 4.4以来,
invalidate()
解决方案似乎不再是必要的,你可以使用其他一些更安全的解决方案。我在回答我自己的问题,希望能帮助那些和我有同样问题的人。
我已经尝试了几种方法来让事情变得更好,甚至是所有臭名昭著的-
webkit-transform: translate3d(0,0,0);
,即使这样也没有工作得太好。让我来和大家分享一下哪些方法有效。
首先,使用最新的API。我使用的是API 15。在您的
AndroidManifest.xml
中,请确保启用 * 硬件加速 *。如果您的API版本不支持此功能,请转到下一位。如果您的版本支持它,则可以通过修改清单来启用它:
另外,确保您的manifest具有您正在使用的最低支持API。由于我使用的是API 15,因此我的manifest具有以下内容:
build.gradle
)* 中值现在,在您的主CSS文件中,为将在WebView中显示的内容添加如下内容:
将其他元素类型添加到body div位上;您可能可以排除图像、
ul
、li
等。将此CSS样式应用于所有内容的原因只是通过反复试验,我发现将其粗暴地应用于所有内容似乎效果最好。对于较大的DOM树,您可能需要更加具体。但是,我不确定规范是什么。当你示例化你的
WebView
时,你需要设置一些设置:倒数第二,但也是最关键的一点:我在阅读
WebView
类的源代码时,发现了这个关于强制重绘的小注解。有一个static final boolean
,当设置为true
时,它将强制视图总是重绘。我对Java语法不是很精通,但我认为你不能直接更改类的静态final属性。所以我最终做的是这样扩展该类:请记住,我使用的是Cordova/PhoneGap,所以我必须从
CordovaWebView
扩展。如果你在onDraw方法中看到,有一个对invalidate
的调用。这将导致视图不断地重绘。但是,我强烈建议添加逻辑,以便只在需要时重绘。最后一步,如果你使用的是Cordova。你必须告诉PhoneGap使用你的新
WebView
类,而不是他们自己的WebView
类。在你的MainActivity
类中,添加以下内容:就是这样!试着运行你的应用程序,看看是否一切都更流畅了。在做所有这些改变之前,页面会显示为白色,没有CSS更改会被应用,直到再次点击屏幕后,动画超级不稳定,甚至不明显。我应该提到的是,动画仍然不稳定,但比以前少了很多。
如果有人对此有任何补充,请在下面评论。我完全意识到可能有更好的方法来做我刚才推荐的事情。
如果我的上述解决方案对您不起作用,您能否描述一下您的具体情况,以及您在Android
WebView
上看到的结果?最后,我已经将这个答案作为 “社区wiki” 启用,因此任何人都可以随时进行调整。
谢谢你!
编辑:
对于最新的PhoneGap,您需要让init()方法看起来更像这样:
zbq4xfa02#
我实施了凯尔的解决方案,它解决了这个问题。然而,我注意到android 4.0.4在应用程序打开时电池消耗很大。而且,在更改后,我有用户抱怨swiftKey键盘不再与我的应用程序一起工作。
我的应用中的每一个更改都是由用户操作触发的,因此我提出了一个修改后的版本,它只在touchEvent之后触发invalidate():
从来没有用Java编程过,所以可能有更好的解决方案来做到这一点。
ru9i0ody3#
re:重绘问题,您可以通过从元素阅读属性来强制重绘
假设您这样做:
如果以后执行此操作:
它将强制重绘。
这样,您就可以有选择性地重新绘制整个页面,而不是一直重新绘制整个页面,这是非常昂贵的
js81xvg64#
对我来说,这个问题只发生在三星设备上。我能够通过禁用WebViews的硬件加速来修复它:
希望能有所帮助。
i2byvkas5#
正如上面和其他地方所指出的-覆盖
View.onDraw()
和调用View.invalidate
将使电池不满意/应用性能将下降。我试着在
WebViewClient.onPageLoaded()
中放置一个无效调用,但这似乎不起作用。虽然我的解决方案可以更好,但它很简单,对我很有效(我只是显示一个Twitter登录)fdbelqdn6#
请也看到我的回答在WebView无法渲染,直到触摸Android 4.2.2,这个想法是导出@奥利维尔的函数到JavaScript,这样你就可以触发从JS在明智的部分无效...我的上帝,又一个黑客!!:)
bihw5rsg7#
我遇到这个问题是因为onPageStared和onPageFinished显示和隐藏了一个加载动画。
因为是从原始网站注入JS做我的菜单和东西,并注意到在onPageFinished上注入JS强制webview绘制内容。
iszxjhcz8#
只要清除oncreate()中的webView缓存,它就对我有效。
laik7k3q9#
您应该通过修改清单来启用硬件:
在您的活动onResume()中
而在onPause()中