这个答案稍后添加:
所以问题是 Adobe 的 Flash Player 在 WebView 内创建了一个 SurfaceView,并且在 SurfaceView 出现和 Flash 引擎费心绘制任何内容之间存在延迟。在那个小间隙中,SurfaceView 看起来完全是黑色的。
我找到的解决方案是继承 WebView 并将自定义的 SurfaceView 添加到视图树。其次,抑制对 Adobe 视图的第一次 draw() 调用也很重要。我的子类 WebView 的代码如下:
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.webkit.WebView;
import android.widget.AbsoluteLayout;
public class FixAdobeWebView extends WebView {
View whiteView;
private boolean eatenFirstFlashDraw;
public FixAdobeWebView(Context context, AttributeSet attrs) {
super(context, attrs);
whiteView = new WhiteSurfaceView(context);
whiteView.setLayoutParams(new AbsoluteLayout.LayoutParams(800, 480, 0, 0));
addView(whiteView);
}
private class WhiteSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
public WhiteSurfaceView(Context context) {
super(context);
getHolder().addCallback(this);
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
Canvas canvas = holder.lockCanvas();
if (canvas != null) {
canvas.drawColor(Color.WHITE);
holder.unlockCanvasAndPost(canvas);
}
}
@Override
public void surfaceCreated(SurfaceHolder holder) { }
@Override
public void surfaceDestroyed(SurfaceHolder holder) { }
}
//
// Override drawChild to eat the first draw of the FlashPaintSurface
//
@Override
protected boolean drawChild (Canvas canvas, View child, long drawingTime) {
if (!eatenFirstFlashDraw && child.getClass().getName().equals("com.adobe.flashplayer.FlashPaintSurface")) {
eatenFirstFlashDraw = true;
return true;
}
return super.drawChild(canvas, child, drawingTime);
}
}
布局 XML 应该声明这个类的一个实例,即:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@android:color/white"
>
<org.test.FixAdobeWebView android:id="@+id/webview1"
android:layout_height="fill_parent"
android:layout_width="fill_parent"
/>
</LinearLayout>
在我运行 CM6.1 的 Nexus One 上,这非常有效,因为在 Flash SurfaceView 开始绘图之前,WebView 显示为纯白色。您可能需要对其进行一些调整,例如摆脱硬编码的 800x480 尺寸,并在不再需要时销毁白色 SurfaceView。
原始(错误)答案:
看起来 Adobe 应该为此负责。
到目前为止,我发现的最不糟糕的解决方法是:
- 将 WebView 父级的背景设为兼容颜色(即白色)。
- 最初隐藏 WebView。
- 等到您获得页面加载事件,然后在一秒延迟后排队运行可显示 WebView。
这意味着您在看到任何东西之前肯定会延迟一秒钟,但它比可怕的黑色闪光 afaik 更不刺耳。
布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@android:color/white"
>
<WebView android:id="@+id/webview1"
android:layout_height="fill_parent"
android:layout_width="fill_parent"
android:visibility="invisible"
/>
</LinearLayout>
代码:
final Handler handler = new Handler();
...
final WebView mWebView1 = (WebView) findViewById(R.id.webview1);
mWebView1.getSettings().setJavaScriptEnabled(true);
mWebView1.getSettings().setPluginsEnabled(true);
mWebView1.setWebViewClient(new WebViewClient() {
@Override
public void onPageFinished(WebView view, String url) {
handler.postDelayed(new Runnable() {
@Override
public void run() {
mWebView1.setVisibility(View.VISIBLE);
}
}, 1000);
}
});
mWebView1.loadUrl("file:///android_asset/graph_01.swf");
可能有更好的方法,尽管这样可以消除对固定延迟的需求......
我已经有一段时间没有用 Flash 做任何事情了,但我似乎记得 Flash 控件有一种方法可以使用浏览器的 Javascript 引擎(快速 Google 会找到 Flex Ajax Bridge,这似乎很可能)。
您可以做的是,通过上述桥接器,使用 ActionScript 调用执行 alert() 的 Javascript 函数。在您的 Java 代码中,您可以将 mWebView1 连接到实现 onJsAlert() 的 WebChromeClient。在该函数中,您可以使 WebView 可见。