Android WebView 呈现空白/白色,视图不会在 css 更改或 HTML 更改时更新,动画不稳定

新手上路,请多包涵

每当我更改 css 类时,更改并不总是出现。当我有一个触摸事件向按钮添加类似向下类名称的内容时,这似乎会发生。该按钮不会更新,页面上的任何其他内容也不会更新。它的工作时间非常不稳定。我还注意到有时我的元素显示为白色,没有任何内容或任何内容。这非常令人沮丧!

原文由 Kyle 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 656
2 个回答

我实施了 kyle 的解决方案并解决了问题。然而,当应用程序打开时,我注意到 android 4.0.4 上的电池消耗量很大。同样在更改之后,我有用户抱怨 swiftKey 键盘不再适用于我的应用程序。

我的应用程序中的每个更改都是由用户操作触发的,因此我想出了一个修改版本,它只在 touchEvent 之后触发 invalidate():

     Handler handler = new Handler();
    public boolean onTouchEvent (MotionEvent event){
        super.onTouchEvent(event);
        handler.postDelayed(triggerInvalidate, 60);
            handler.postDelayed(triggerInvalidate, 300);
        return true;
    }

    private Runnable triggerInvalidate=new Runnable(){
        public void run(){
            invalidate();
        }
    };

从来没有用 Java 进行过任何编程,所以可能有更好的解决方案来做到这一点。

原文由 Olivier 发布,翻译遵循 CC BY-SA 3.0 许可协议

笔记:

从 Android 4.4+ 开始有更好的解决方案。这是一个名为 CrossWalk 的替代品 WebView 替代品。它使用最新的 Chromium-kit,非常棒。你可以在这里阅读它: crosswalk-project.org

此外,似乎自 Android 4.4 以来,不再需要 invalidate() 解决方案,您可以使用其他一些更安全的答案。我只会使用这种 invalidate() 方法作为最后的努力。


我正在回答我自己的问题,希望能帮助那些和我有同样问题的人。

我已经尝试了几种方法来让事情变得更好,甚至是所有臭名昭著的 - webkit-transform: translate3d(0,0,0); 即使那样也不太奏效。

让我与您分享有效的方法。

首先,使用最新的 API。我正在使用 API 15。在你的 AndroidManifest.xml 中,确保启用 _硬件加速_。如果您的 API 版本不支持此功能,请继续下一步。

如果您的版本确实支持它,您可以通过修改清单来启用它:

 <application
   ...
   android:hardwareAccelerated="true">

此外,请确保您的清单具有对您正在使用的 API 的最低支持 API。因为我使用的是 API 15,所以这是我的清单:

 <uses-sdk
    android:minSdkVersion="15"
    android:targetSdkVersion="15" />

更新:您现在应该修改您的值 build.gradle

现在,在您的主要 CSS 文件中,对于将在 WebView 中显示的内容,添加如下内容:

 body div {
    -webkit-transform: translate3d(0,0,0);
}

使用您拥有的任何其他元素类型添加到 body div 位;您可能可以排除图像, ulli 等。将此 CSS 样式应用于所有内容的原因只是通过反复试验,我发现将其应用于所有内容似乎效果最好。对于更大的 DOM 树,您可能需要更加具体。但是,我不确定规格是什么。

当您实例化您的 WebView 时,您需要设置一些设置:

 @Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    super.loadUrl("file:///android_asset/www/index.html");
    appView.getSettings().setRenderPriority(RenderPriority.HIGH);
    appView.getSettings()
            .setPluginState(WebSettings.PluginState.ON_DEMAND);
}

倒数第二个但至关重要的一点:我正在阅读 WebView 类的源代码,发现这个关于强制重绘的小注释。有一个 static final boolean ,当设置为 true 将强制视图始终重绘。我对 Java 语法不是很了解,但我认为您不能直接更改类的静态最终属性。所以我最终做的是像这样扩展课程:

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

}

请记住,我使用的是 Cordova/PhoneGap,因此我必须从 CordovaWebView 进行扩展。如果您在 onDraw 方法中看到,有一个对 invalidate 的调用。这将导致视图不断重绘。但是,我强烈建议添加逻辑以仅在需要时重绘。

如果您使用的是 Cordova,则还有最后一步。您必须告诉 PhoneGap 使用您的新 WebView 类而不是他们自己的 WebView 类。在您的 MainActivity 类中,添加以下内容:

 public void init(){
    CordovaWebView webView = new MyWebView(MainActivity.this);
    super.init(webView, new CordovaWebViewClient(this, webView), new CordovaChromeClient(this, webView));
}

而已!尝试运行您的应用程序,看看一切是否更流畅。在进行所有这些更改之前,页面会显示为白色,直到再次点击屏幕后才会应用任何 CSS 更改,动画非常不稳定甚至不明显。我应该提到动画仍然不稳定,但远没有以前那样不稳定。

如果有人对此有任何补充,请在下面发表评论。我总是对优化持开放态度;而且我完全知道可能有更好的方法来完成我刚刚推荐的事情。

如果我的上述解决方案对您不起作用,您能否描述您的具体情况以及您在 Androids WebView 上看到的结果?

最后,我已将此答案启用为 “社区维基” ,因此任何人和每个人都可以随意进行调整。

谢谢!


编辑:

使用最新的 PhoneGap,您需要让您的 init() 方法看起来更像这样:

 public void init(){
    CordovaWebView webView = new MyWebView(MainActivity.this);
    super.init(webView, new IceCreamCordovaWebViewClient(this, webView), new CordovaChromeClient(this, webView));
}

原文由 Kyle 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题