web-dev-qa-db-fra.com

getLocationOnScreen () vs getLocationInWindow ()

Quelle est la difference entre screen et view dans le contexte de ces deux méthodes?

J'ai un bouton et je veux obtenir la coordonnée x de son centre.

Je suppose que cela suffirait:

public int getButtonXPosition() {
    return (button.getLeft()+button.getRight())/2;
}

mais alors, quelle différence cela ferait-il si j'aurais utilisé

getLocationOnScreen() ou getLocationInWindow()?

(en ajoutant la moitié de la largeur du bouton à cela, bien sûr)

63
Elad Benda

Je ne pense pas que cette réponse est correcte. Si je crée un nouveau projet et ne modifie que MainActivity en ajoutant l'extrait de code 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 vais voir imprimé sur la console 108 108. Ceci utilise un Nexus 7 sous 4.3. J'ai des résultats similaires en utilisant des émulateurs exécutant Android aussi anciennes que 2.2.

Les fenêtres d'activité normale auront FILL_PARENTxFILL_PARENT en tant que WindowManager.LayoutParams, ce qui les placera à la taille de la totalité de l'écran. La fenêtre est aménagée en dessous (en ce qui concerne l'ordre z, pas les coordonnées y) de la barre d'état et d'autres décorations. Je pense donc qu'un tableau plus précis serait:

|--phone screen-----activity window---| 
|--------status bar-------------------| 
|                                     | 
|                                     | 
|-------------------------------------| 

Si vous parcourez les sources de ces deux méthodes, vous verrez que getLocationInWindow parcourt la hiérarchie des vues jusqu'à la RootViewImpl, en faisant la somme des coordonnées de la vue et en soustrayant les décalages de défilement parent. Dans le cas que j'ai décrit ci-dessus, ViewRootImpl obtient la hauteur de la barre d'état de WindowSession et la transmet via fitSystemWindows à ActionBarOverlayLayout, ce qui ajoute cette valeur à la hauteur de la barre d'action. ActionBarOverlayLayout prend ensuite cette valeur cumulée et l'applique à sa vue de contenu, qui est le parent de votre mise en page, sous forme de marge.

Votre contenu est donc placé plus bas que la barre d'état, pas à cause de la fenêtre commençant à une coordonnée y inférieure à celle de la barre d'état, mais à la suite de l'application d'une marge à la vue de contenu de votre activité.

Si vous examinez la source getLocationOnScreen, vous verrez qu'elle appelle simplement getLocationInWindow, puis ajoute les coordonnées gauche et supérieure de la fenêtre (qui sont également transmises à View par ViewRootImpl, qui les récupère de la WindowSession). Dans le cas normal, ces deux valeurs seront nulles. Dans certaines situations, ces valeurs peuvent être non nulles, 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. Ces deux valeurs diffèrent uniquement dans des cas particuliers, tels que des boîtes de dialogue dans lesquelles la fenêtre est réellement décalée.

110
groucho

getLocationOnScreen () obtiendra l'emplacement basé sur le écran du téléphone.

getLocationInWindow () obtiendra l'emplacement basé sur la fenêtre d'activité.

Pour le activité normale (activité non plein écran), la relation entre l'écran du téléphone et la fenêtre d'activité est décrite ci-dessous:

| --écran du téléphone ------------------
| ----------- (barre d'état
------------------
| |
| ------------------------------------------- |
| ----------- (fenêtre d'activité
------ ------- |
| |
| |
| |
| |
| |
| |
| ------------------------------------------- |

Pour la coordonnée x, la valeur des deux méthodes est généralement la même.

Pour la coordonnée y, les valeurs ont une différence pour la hauteur de la barre d'état.

24
Ivan

La réponse acceptée actuellement est un peu verbeuse. En voici un plus court.

getLocationOnScreen() et getLocationInWindow() renvoient normalement les mêmes valeurs. En effet, la fenêtre a normalement la même taille que l’écran. Cependant, la fenêtre est parfois plus petite que l'écran. Par exemple, dans un Dialog ou un clavier système personnalisé.

Ainsi, si vous savez que les coordonnées souhaitées sont toujours relatives à l'écran (comme dans une activité normale), vous pouvez utiliser getLocationOnScreen(). Toutefois, si votre vue se trouve dans une fenêtre pouvant être plus petite que l'écran (comme dans un dialogue ou un clavier personnalisé), utilisez getLocationInWindow().

Connexes

4
Suragch