在 Nexus 7 或三星 Galaxy Nexus(可能还有其他设备)等设备上,我注意到了这个问题(见图)。这是在 WebView 中的硬件加速模式下运行的。但是,当我将其设置为软件渲染模式时,它显示正常,但会稍微降低性能。我很想学习如何解决这个问题,并且只在 WebViews 上使用硬件加速而不是软件模式。
渲染不良(在三星 Galaxy Nexus 上运行):
正确的渲染(在 Motorola Bionic 上运行):
安卓清单:
<uses-sdk
android:minSdkVersion="10"
android:targetSdkVersion="17" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<supports-screens
android:resizeable="true"
android:smallScreens="true"
android:normalScreens="true"
android:largeScreens="true"
android:xlargeScreens="true"
android:anyDensity="true" />
<application
android:allowBackup="true"
android:hardwareAccelerated="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
....
</application>
</manifest>
Java代码:
....
@TargetApi(VERSION_CODES.HONEYCOMB)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
try{
db = new DatabaseHandler(this);
tts = new TextToSpeech(this, this);
handler = new Handler();
frame = new FrameLayout(this);
frame.setBackgroundColor(Color.GRAY);
wv = new WebView(this);
wv.setScrollBarStyle(WebView.SCROLLBARS_INSIDE_OVERLAY);
frame.addView(wv);
wv.setVisibility(WebView.INVISIBLE);
iv = new ImageView(this);
Drawable d = Drawable.createFromStream(getAssets().open("www/img/loading.jpg"), null);
iv.setImageDrawable(d);
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT,
FrameLayout.LayoutParams.MATCH_PARENT);
iv.setLayoutParams(params);
frame.addView(iv);
WebSettings ws = wv.getSettings();
ws.setRenderPriority(RenderPriority.HIGH);
ws.setJavaScriptEnabled(true);
ws.setAllowFileAccess(true);
if (Build.VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN)
ws.setAllowUniversalAccessFromFileURLs(true);
ws.setCacheMode(WebSettings.LOAD_NO_CACHE);
SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(this);
if(Build.VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB && !pref.getBoolean("prefHardware", true)){
wv.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
wv.setWebChromeClient(new WebChromeClient(){
//int id = 0;
@Override
public boolean onConsoleMessage(ConsoleMessage consoleMessage) {
// TODO Auto-generated method stub
// Log.d("JS Console", consoleMessage.message() + " at " + consoleMessage.sourceId() + ":" + consoleMessage.lineNumber());
//Toast.makeText(TaskRunner.this, consoleMessage.message() + " at " + consoleMessage.sourceId() + ":" + consoleMessage.lineNumber(), Toast.LENGTH_LONG).show();
// NotificationCompat.Builder mBuilder =
// new NotificationCompat.Builder(TaskRunner.this)
// .setSmallIcon(R.drawable.ic_launcher)
// .setContentTitle("Console Message")
// .setContentText(consoleMessage.message() + " at " + consoleMessage.sourceId() + ":" + consoleMessage.lineNumber());
//// mBuilder.setContentIntent(null);
// NotificationManager mNotificationManager =
// (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// // mId allows you to update the notification later on.
// mNotificationManager.notify(id++, mBuilder.build());
return super.onConsoleMessage(consoleMessage);
}
});
wv.setWebViewClient(new WebViewClient(){
@Override
public void onPageFinished(WebView view, String url) {
// TODO Auto-generated method stub
//Log.i("TEST", "TEST");
//hideLoading();
super.onPageFinished(view, url);
}
@Override
public void onPageStarted(WebView view, String url,
Bitmap favicon) {
// TODO Auto-generated method stub
if(frame.getChildAt(frame.getChildCount()-1) != iv){
frame.addView(iv);
wv.setVisibility(WebView.INVISIBLE);
}
super.onPageStarted(view, url, favicon);
}
@Override
public void onReceivedError(WebView view, int errorCode,
String description, String failingUrl) {
// TODO Auto-generated method stub
Log.e("ERROR", description);
super.onReceivedError(view, errorCode, description, failingUrl);
}
});
MyJavascriptInterface ji = new MyJavascriptInterface();
wv.addJavascriptInterface(ji, "ji");
setOrientation();
wv.loadUrl("file:///android_asset/www/index.html");
setContentView(frame);
}
catch(Exception e){
}
}
....
HTML 文件:
<!DOCTYPE html>
<html>
<head>
<title>Task Player</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="format-detection" content="telephone=no" />
......
</head>
<body>
<div id="gamespacer">
<div id="instructions-block">
<div id="explaination">
</div>
<div id="instructions-close">
<br /><br />
<div class="btn btn-large btn-info" id="speak-tts">Speak</div>
<br /><br />
<input type='checkbox' id='auto-speak' value="yes" checked="checked" />Auto speak
</div>
<div id="drag-container">
<div id='drag'>
<span id='au'><img src="img/arrow-up.png" alt="" width="45" /></span>
<span id='ad'><img src="img/arrow-down.png" alt="" width="45"/></span>
</div>
</div>
</div>
</div>
<div id="play-container">
<canvas>
</canvas>
</div>
<div class="centerMe" id="rotate" style="display: none;"><p style="font-size: 24px; margin-top: 20px">Rotate the device to play the game.</p></div>
<div id="winScreen">
<div id="points">
You Got<br/>
<div id="mypoints">0</div>
Points
</div>
<a href="#" id='done' class="btn btn-large btn-inverse">Done</a>
</div>
....
</body>
</html>
CSS:
#winScreen{
display: none;
width: 100%;
height: 100%;
text-align: center;
background-color: green;
font-size: 24px;
margin: 0 auto;
position: absolute;
left: 0px;
top: 0px;
}
#points {
padding-top: 110px;
color: yellow;
margin-bottom: 10px;
}
#mypoints{
margin: 10px;
}
.button{
margin: 0 auto;
margin-top: 50px;
}
#play-container{
width: 100%;
height: 100%;
margin: 0 auto;
text-align: center;
}
canvas {
background-color: white;
position: absolute;
top: 0px;
left: 0px;
}
#gamespacer {
}
#instructions-block {
position: absolute;
left: 0px;
top: -144px;
width: 100%;
background-color: white;
z-index: 1;
}
#instructions-content {
margin-top: 5px;
}
#instructions-close {
text-align: center;
margin-bottom: 10px;
}
#explaination {
margin: 5px;
font-size: 24px;
line-height: 1;
position: relative;
width: 100%
height: 100%
}
#drag-container{
width: 100%;
}
#drag {
position: absolute;
left: 92%;
margin-top: 5px;
}
#au{
display: none;
pointer-events: none;
}
#ad {
pointer-events: none;
}
body{
-webkit-user-select: none;
user-select: none;
-webkit-touch-callout: none;
touch-callout: none;
-webkit-tap-highlight-color: rgba(0,0,0,0);
tap-highlight-color: rgba(0,0,0,0);
}
更新 1
所以我尝试了以下代码,但效果不佳。
wv.setLayerType(View.LAYER_TYPE_HARDWARE, null);
更新 2
到目前为止,据我所知,这只发生在 Google 制造的设备(如 Nexus)上。那么,他们的内核或视频驱动程序中是否存在错误?或者,Android 4.2.2 可能有问题。
如果您对如何解决此问题有任何想法,请告诉我。
更新 3
我做了一个测试项目供你尝试。玩弄缩放级别并移动窗口。让我知道它是否有什么奇怪的地方。到目前为止,它使用 Android 4.2.2
谢谢!