Je ne pense pas que cette réponse est correcte. Si je crée un nouveau projet, et que je modifie uniquement l'activité principale en ajoutant l'extrait suivant :
public boolean dispatchTouchEvent(MotionEvent ev) {
View contentsView = findViewById(android.R.id.content);
int test1[] = new int[2];
contentsView.getLocationInWindow(test1);
int test2[] = new int[2];
contentsView.getLocationOnScreen(test2);
System.out.println(test1[1] + " " + test2[1]);
return super.dispatchTouchEvent(ev);
}
Je verrai s'afficher dans la console 108 108
. J'utilise une Nexus 7 sous la version 4.3. J'ai obtenu des résultats similaires avec des émulateurs utilisant des versions d'Android aussi anciennes que la 2.2.
Les fenêtres d'activité normale auront pour paramètres de disposition WindowManager.LayoutParams FILL_PARENTxFILL_PARENT, ce qui leur permet de s'étendre à la taille de l'écran entier. La fenêtre est disposée sous (en ce qui concerne l'ordre z, pas les coordonnées y) la barre d'état et d'autres décorations, donc je pense qu'un tableau plus précis serait :
|--phone screen-----activity window---|
|--------status bar-------------------|
| |
| |
|-------------------------------------|
Si vous parcourez la source de ces deux méthodes, vous verrez que getLocationInWindow
parcourt la hiérarchie des vues de votre vue jusqu'au RootViewImpl, en additionnant les coordonnées de la vue et en soustrayant les décalages de défilement des parents. en soustrayant les décalages de défilement du parent. Dans le cas que j'ai décrit ci-dessus, le ViewRootImpl obtient la hauteur de la barre d'état de la WindowSession et la transmet, via fitSystemWindows, à l'ActionBarOverlayLayout, qui ajoute cette valeur à la hauteur de la barre d'action. L'ActionBarOverlayLayout prend ensuite cette valeur additionnée et l'applique à sa vue de contenu, qui est le parent de votre mise en page, comme une marge.
Ainsi, votre contenu est disposé plus bas que la barre d'état, non pas parce que la fenêtre commence à une coordonnée y inférieure à celle de la barre d'état, mais parce qu'une marge est appliquée à la vue du contenu de votre activité.
Si vous regardez dans le getLocationOnScreen
source que vous verrez qu'elle appelle simplement getLocationInWindow
et ajoute ensuite les coordonnées de gauche et de haut de la fenêtre (qui sont également transmises à la vue par ViewRootImpl, qui les récupère dans WindowSession). Dans le cas normal, ces valeurs seront toutes deux égales à zéro. Dans certaines situations, ces valeurs peuvent être différentes de zéro, par exemple une fenêtre de dialogue placée au milieu de l'écran.
Donc, pour résumer : La fenêtre d'une activité normale remplit tout l'écran, même l'espace sous la barre d'état et les décorations. Les deux méthodes en question renverront les mêmes coordonnées x et y. Ce n'est que dans des cas particuliers, comme les boîtes de dialogue où la fenêtre est effectivement décalée, que ces deux valeurs seront différentes.
1 votes
Avec Android N et son support multi-fenêtres ( developer.Android.com/preview/features/multi-window.html ), vous devriez probablement préférer getLocationInWindow() à getLocationOnScreen(), car cette dernière peut entraîner un comportement inattendu.