На некоторых устройствах, таких как Nexus 7 или Samsung Galaxy Nexus (возможно, другие), я заметил эту проблему (см. рисунок). Это выполняется в режиме ускорения аппаратного обеспечения в WebView. Однако, когда я перехожу к режиму рендеринга программного обеспечения, он отображается в хорошем состоянии, но немного замедляет работу. Я хотел бы узнать, как исправить эту проблему, и использовать только аппаратное ускорение в WebViews, а не в программном режиме.
Плохая рендеринг (работает на Samsung Galaxy Nexus):
Правильная рендеринг (работает на Motorola Bionic):
Android Manifest:
<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
Спасибо!