62 votes

Coordonnées incorrectes de getLocationOnScreen/getLocationInWindow

Un appel à getLocationOnScreen() ou getLocationInWindow() les deux me donnent un top/Y coordonnée qui est environ ~30px (hauteur de la barre d'état/notifications) trop loin vers le bas. Le site left/X Les coordonnées sont exactes.

Comme je l'ai indiqué plus haut, je pense que la différence est due à la barre d'état/notification... Je peux me tromper. Je pense que je peux résoudre ce problème si je peux déterminer la taille de la barre de notification, mais j'ai du mal à le faire.

Toute aide serait grandement appréciée.

86voto

nimph Points 493

J'ai fini par résoudre ce problème en déterminant la hauteur de la barre d'état/notification de la manière suivante :

View globalView = ...; // the main view of my activity/application

DisplayMetrics dm = new DisplayMetrics();
this.getWindowManager().getDefaultDisplay().getMetrics(dm);
int topOffset = dm.heightPixels - globalView.getMeasuredHeight();

View tempView = ...; // the view you'd like to locate
int[] loc = new int[2]; 
tempView.getLocationOnScreen(loc);

final int y = loc[1] - topOffset;

0 votes

Cela fonctionne dans une configuration normale, mais si l'activité ajuste la hauteur du 'globalView' lorsque le SoftInput/Keyboard est ouvert, alors la hauteur du clavier est également comptée dans 'topOffset', ce qui donne une valeur erronée pour 'y'.

8 votes

int [] locInWindow = new int [2]; globalView.getLocationInWindow(locInWindow); topOffset = locInWindow[1]; //Compute topOffset en obtenant la coordonnée Y de globalView

0 votes

@ThammeGowda pourriez-vous m'expliquer comment obtenir le décalage du haut du clavier lorsque celui-ci est ouvert ?

10voto

satur9nine Points 3901

Voici comment j'aime obtenir la hauteur de la barre d'état, et ajuster le décalage :

final int[] location = new int[2];
anchor.getLocationInWindow(location); // Includes offset from status bar, *dumb*
Rect anchorRect = new Rect(location[0], location[1],
        location[0] + anchor.getWidth(), location[1] + anchor.getHeight());

anchor.getRootView().findViewById(android.R.id.content).getLocationInWindow(location);
int windowTopOffset = location[1];
anchorRect.offset(0, -windowTopOffset);

0 votes

Pourquoi est-il stupide que l'emplacement dans la fenêtre comprenne le décalage par rapport à la barre d'état ? Vous demandez l'emplacement dans la fenêtre alors à quoi d'autre pouvez-vous vous attendre ?

2 votes

On pourrait supposer que la fenêtre se trouve sous la barre d'état, et donc que le décalage n'inclurait pas la hauteur de la barre d'état.

0 votes

Tu confonds Fenêtre et Ecran je crois.

4voto

user330844 Points 366

J'ai le même problème, essayez d'utiliser

offset = myView.GetOffsetY();

et ajustez votre coordonnée Y par cette valeur, par exemple.

coordY -= offset;

La classe qui propose la "méthode" :

class MyView extends View {

  public int GetOffsetY() {
    int mOffset[] = new int[2];
    getLocationOnScreen( mOffset );
    return mOffset[1]; 
  }

}

0 votes

Je ne vois pas "getOffsetY()". De quelle classe s'agit-il ?

0 votes

Je suis désolé, j'ai oublié de poster la méthode, dans la classe MyView extends View { public int GetOffsetY() { int mOffset[] = new int[2] ; getLocationOnScreen( mOffset ) ; return mOffset[1] ; }

4voto

groucho Points 588

Cette réponse n'indique pas comment obtenir la hauteur de la barre d'état, mais elle explique le comportement de la fonction getLocationOnScreen() y getLocationInWindow() renvoyant la même valeur.

Dans le cas d'une activité normale (pas un dialogue), vous devez vous attendre à ce que ces deux méthodes renvoient la même valeur. Une fenêtre s'affiche sous la barre d'état (dans l'ordre z et non en coordonnées y). Ces méthodes ne peuvent donc pas être utilisées pour déterminer la hauteur de la barre d'état.

https://stackoverflow.com/a/20154562/777165

0 votes

Dans la vue Dialog, cela fonctionne bien si la fenêtre plein écran n'est pas définie comme vraie, mais si elle est définie comme suit : <item name="Android:windowFullscreen">true</item> alors la valeur n'est pas correcte, il faut donc soustraire le 'topOffset'.

0voto

Hussien Fahmy Points 314

Comme l'a dit @ThammeGowda, la bonne réponse donnera une position incorrecte lorsque le clavier est affiché, mais vous devez toujours calculer le décalage supérieur de la barre d'action, il suffit donc d'obtenir directement la taille de la barre d'action.

fun View.getPosition(): Point {
    val tv = TypedValue()
    if (context.theme.resolveAttribute(android.R.attr.actionBarSize, tv, true)) {
        val actionBarHeight =
            TypedValue.complexToDimensionPixelSize(tv.data, resources.displayMetrics)

        val loc = IntArray(2).apply { getLocationInWindow(this) }

        val newY = loc[1] - actionBarHeight - (measuredHeight / 2) // to get the position in the middle of the view

        return Point(loc[0], newY)
    }
    return Point(0,0)
}

enter image description here

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X