Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/html/76.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android WebView呈现为空白/白色,视图不';更新css更改或HTML更改时,动画不稳定_Android_Html_Css_Cordova - Fatal编程技术网

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

Android WebView呈现为空白/白色,视图不';更新css更改或HTML更改时,动画不稳定,android,html,css,cordova,Android,Html,Css,Cordova,每当我更改css类时,这些更改并不总是出现。这似乎发生在我有一个触摸事件,它会在按钮上添加一个类似于向下类名的内容。按钮不会更新,页面上的其他任何内容也不会更新。它工作的时间非常不稳定。我还注意到,有时我的元素显示为白色,没有内容或任何东西。这太令人沮丧了 注意: Android 4.4+有一个更好的解决方案。这是一个叫做人行横道的替代品。它使用最新的铬试剂盒,非常棒。你可以在这里读到: 此外,自Android 4.4以来,似乎不再需要invalidate()解决方案,您可以使用其他更安全的解决

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

注意:
Android 4.4+有一个更好的解决方案。这是一个叫做人行横道的替代品。它使用最新的铬试剂盒,非常棒。你可以在这里读到:

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


我在回答我自己的问题,希望能帮助人们解决和我一样的问题

我已经尝试了几种方法来改善情况,甚至是臭名昭著的-
webkit转换:translate3d(0,0,0)即使这样也不太管用

让我和你分享一下你的工作

首先,使用最新的API。我使用的是API 15。在您的
AndroidManifest.xml
中,确保启用硬件加速。如果您的API版本不支持这一点,那么请转到下一位

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

<application
   ...
   android:hardwareAccelerated="true">
在body div位上添加您拥有的任何其他元素类型;您可能会排除图像、
ul
li
,等等。将此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
类的源代码,发现了这个关于强制重画的小评论。有一个
静态最终布尔值
,当设置为
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();
    }

}
请记住,我使用的是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()方法看起来更像这样:

body div {
    -webkit-transform: translate3d(0,0,0);
}
public void init(){
    CordovaWebView webView = new MyWebView(MainActivity.this);
    super.init(webView, new IceCreamCordovaWebViewClient(this, webView), new CordovaChromeClient(this, webView));
}

我实施了凯尔的解决方案,解决了问题。然而,当android 4.0.4应用程序打开时,我注意到一个巨大的电池消耗。同样,在更改之后,我也有用户抱怨快捷键键盘不再适用于我的应用程序

我的应用程序中的每一个更改都是由用户操作触发的,因此我提出了一个修改版本,该版本仅在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的函数导出到JavaScript,以便您可以在合理的部分从JS触发失效。。。天哪,又是一个黑客!!:)

re:重画问题,您可以通过从元素读取属性来强制重画

因此,假设你这样做:

$('#myElement').addClass('foo'); // youre not seeing this take effect
如果您在之后执行此操作:

$('#myElement').width();
这将迫使重新绘制


通过这种方式,您可以选择重新绘制整个页面,而不是像上面和其他地方指出的那样一直重新绘制整个页面,这是非常昂贵的

——重写
View.onDraw()
并调用
View.invalidate
将导致电池性能不理想/应用程序性能下降。您还可以手动执行“无效化”
调用,每次x毫秒,如下所示

/**
 * 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);
        }
    });
}

我尝试在
WebViewClient.onPageLoaded()
中调用invalidate,但似乎不起作用。虽然我的解决方案可能会更好,但它很简单,而且对我很有效(我只是显示一个twitter登录名)

我遇到了这个问题,因为OnPageStarted和onPageFinished显示并隐藏了加载动画

因为注入JS会从原始网站上执行我的菜单和内容,并注意到在onPageFinished上注入JS会强制webview绘制内容。下面是一个可以在onPageFinished末尾添加内容的示例

view.loadUrl("javascript:(function() { var select = document.getElementsByClassName('something')[0]\r\n" + 
                            "                     if(select)" +
                            "                       select.style.display = 'none';})()");

对我来说,这个问题只发生在三星设备上。我可以通过为我们禁用硬件加速来修复它
view.loadUrl("javascript:(function() { var select = document.getElementsByClassName('something')[0]\r\n" + 
                            "                     if(select)" +
                            "                       select.style.display = 'none';})()");
webView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
webView.clearCache(true);