Note :
Il y a une meilleure solution à partir d'Android 4.4+. Il s'agit d'un drop-in WebView
remplacement appelé CrossWalk . Il utilise la dernière version de Chromium-kit et il est fantastique. Vous pouvez en savoir plus à ce sujet ici : projet-passerelle.org
De plus, il semble que depuis Android 4.4, la invalidate()
n'est plus nécessaire et vous pouvez vous en sortir en utilisant d'autres solutions plus sûres. Je n'utiliserais que ceci invalidate()
comme un dernier effort.
Je réponds à ma propre question dans l'espoir d'aider les personnes qui ont les mêmes problèmes que moi.
J'ai essayé plusieurs méthodes pour améliorer les choses, même la fameuse - webkit-transform: translate3d(0,0,0);
Même ça, ça n'a pas très bien marché.
Laissez-moi partager avec vous ce qui a fonctionné.
Tout d'abord, utilisez l'API la plus récente. J'utilise l'API 15. Dans votre AndroidManifest.xml
assurez-vous d'activer accélération matérielle . Si votre version de l'API ne prend pas en charge cette fonction, passez à l'étape suivante.
Si votre version le prend en charge, vous pouvez l'activer en modifiant votre manifeste :
<application
...
android:hardwareAccelerated="true">
Assurez-vous également que votre manifeste possède l'API minimale supportée par celle que vous utilisez. Comme j'utilise l'API 15, voici ce que contient mon manifeste :
<uses-sdk
android:minSdkVersion="15"
android:targetSdkVersion="15" />
( Mise à jour vous devez maintenant modifier ces valeurs dans votre build.gradle
)
Maintenant, dans votre fichier CSS principal pour ce qui sera présenté dans une WebView, ajoutez quelque chose comme ceci :
body div {
-webkit-transform: translate3d(0,0,0);
}
Ajoutez à l'élément div body tout autre type d'élément dont vous disposez ; vous pouvez probablement exclure les images, ul
, li
etc. La raison de l'application de ce style CSS à tous les éléments est le résultat d'essais et d'erreurs, et j'ai constaté que l'application brute à tous les éléments semble fonctionner le mieux. Avec un arbre DOM plus grand, vous devrez peut-être être plus spécifique. Je ne suis pas sûr de la spécification, cependant.
Lorsque vous instanciez votre WebView
il y a certains paramètres que vous devez définir :
@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);
}
Avant-dernière, mais cruciale partie : J'étais en train de lire le code source du WebView
et j'ai trouvé ce petit commentaire minuscule sur le redécoupage forcé. Il existe un static final boolean
qui, lorsqu'il est réglé sur true
obligera la vue à toujours se redessiner. Je ne suis pas très au fait de la syntaxe Java, mais je ne pense pas que l'on puisse modifier directement un attribut statique final d'une classe. Donc, ce que j'ai fini par faire, c'est d'étendre la classe comme suit :
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();
}
}
Gardez à l'esprit que j'utilise Cordova/PhoneGap, et que j'ai donc dû m'étendre à partir de la base de données de l'UE. CordovaWebView
. Si vous voyez dans la méthode onDraw, il y a un appel à invalidate
. La vue sera ainsi constamment redessinée. Je vous recommande vivement d'ajouter une logique permettant de ne redessiner que lorsque vous en avez besoin.
Il y a une dernière étape, si vous utilisez Cordova. Vous devez indiquer à PhoneGap d'utiliser votre nouvelle application WebView
au lieu de leur propre classe WebView
classe. Dans votre MainActivity
ajoutez ceci :
public void init(){
CordovaWebView webView = new MyWebView(MainActivity.this);
super.init(webView, new CordovaWebViewClient(this, webView), new CordovaChromeClient(this, webView));
}
C'est tout ! Essayez d'exécuter votre application et voyez si tout est beaucoup plus fluide. Avant d'effectuer tous ces changements, les pages apparaissaient en blanc, aucun changement CSS n'était appliqué jusqu'à ce que vous tapotiez à nouveau sur l'écran, les animations étaient très irrégulières ou même imperceptibles. Je dois préciser que les animations sont toujours hachées, mais beaucoup moins qu'avant.
Si quelqu'un a quelque chose à ajouter à cela, il suffit de le commenter ci-dessous. Je suis toujours ouvert aux optimisations ; et je suis pleinement conscient qu'il peut y avoir de meilleures façons de faire ce que je viens de recommander.
Si ma solution ci-dessus n'a pas fonctionné pour vous, pourriez-vous décrire votre situation spécifique et les résultats que vous obtenez avec les Androïdes. WebView
?
Enfin, j'ai activé cette réponse comme un "wiki communautaire" alors n'hésitez pas à faire des ajustements.
Gracias.
Editar:
Avec la dernière version de PhoneGap, votre méthode init() devra ressembler davantage à ceci :
public void init(){
CordovaWebView webView = new MyWebView(MainActivity.this);
super.init(webView, new IceCreamCordovaWebViewClient(this, webView), new CordovaChromeClient(this, webView));
}