Je suis en train de créer une application qui crée de petites animations de sprite qui se promènent sur votre écran.
J'ai une activité principale, avec un bouton "démarrer le service". Cela démarre un service, qui (dans onCreate()
) crée une vue en plein écran et la attache au gestionnaire de fenêtres principal.
Cette partie fonctionne parfaitement. Elle remplit l'écran, et vous pouvez quitter l'application, et les animations resteront visibles au-dessus de tout.
Le problème survient lorsque vous tournez l'appareil.
Les sprites se sont déplacés au milieu de l'écran, mais c'est un problème sans rapport; l'important ici est le cadre de délimitation sombre — ce cadre montre le canevas dans lequel je suis autorisé à dessiner, et il doit remplir tout l'écran
La vue est toujours en mode portrait, même si tous les autres agencements semblent s'être mis à jour correctement.
Une partie du problème vient de la manière dont j'ai spécifié les dimensions de la vue. J'ai utilisé des indicateurs pour spécifier "plein écran", mais cela n'a pas réglé la largeur et la hauteur de la vue pour correspondre aux dimensions de l'écran. Ainsi j'ai dû les définir manuellement au démarrage.
Je ne connais pas de moyen de mettre à jour la largeur et la hauteur de la vue une fois que la vue est créée, mais j'ai l'impression que je dois le faire, car les dimensions de la vue déterminent les dimensions du canevas.
Mon service crée la vue de la manière suivante :
public class WalkerService extends Service {
private WalkerView vue;
@Override
public void onCreate() {
super.onCreate();
final WindowManager wm = (WindowManager)getSystemService(WINDOW_SERVICE);
final DisplayMetrics metrics = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(metrics);
vue = new WalkerView(this); // s'étend à SurfaceView
final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY, // TYPE_SYSTEM_ALERT est refusé dans apiLevel >=19
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN,
PixelFormat.TRANSLUCENT
);
vue.setFitsSystemWindows(false); // nous permet de dessiner par-dessus la barre d'état, la barre de navigation
// ici je définis _manuellement_ les dimensions, car sinon cela se met par défaut à un carré (quelque chose comme 1024x1024)
params.width = metrics.widthPixels;
params.height = metrics.heightPixels;
wm.addView(vue, params);
}
}
J'ai essayé d'écouter les changements d'orientation, et de tourner la vue quand cela se produit :
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
vue.setRotation(
newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE
? 90.0f
: 0.0f
);
}
Mais setRotation()
ne semblait pas affecter la largeur
et la hauteur
de ma vue, ni ne changeait l'angle auquel le canevas était rendu.
Suis-je en train de mal comprendre la manière de créer une superposition en plein écran ? Comment puis-je maintenir la capacité de dessiner sur tout l'écran, quelle que soit l'orientation (et même lorsque mon application n'est pas l'application active) ?
Peut-être cela est-il lié au fait que j'attache ma vue au gestionnaire de fenêtres du service Windows — peut-être cela signifie-t-il que ma vue a un parent étrange (je pourrais imaginer que peut-être la vue racine ne serait pas affectée par l'orientation, ou qu'elle n'aurait pas des limites définies pour que les enfants s'étirent pour remplir).
Le code source complet est public sur GitHub au cas où j'aurais omis des informations utiles ici.
WalkerView.java
peut être particulièrement pertinent, alors le voici.