web-dev-qa-db-fra.com

Comment obtenir les coordonnées absolues d'une vue

J'essaie d'obtenir les coordonnées absolues en pixels de l'écran du coin supérieur gauche d'une vue. Cependant, toutes les méthodes que je peux trouver, telles que getLeft() et getRight() ne fonctionnent pas car elles semblent toutes être relatives au parent de la vue, me donnant ainsi 0. Quelle est la bonne façon de faire cela?

Si cela peut vous aider, c’est pour un jeu qui consiste à "remettre l’image en ordre". Je veux que l'utilisateur puisse dessiner une boîte pour sélectionner plusieurs pièces. Mon hypothèse est que le moyen le plus simple de procéder consiste à getRawX() et getRawY() à partir de MotionEvent, puis à comparer ces valeurs avec le coin supérieur gauche de la présentation contenant les pièces. Connaissant la taille des pièces, je peux ensuite déterminer le nombre de pièces sélectionnées. Je réalise que je peux utiliser getX() et getY() sur le MotionEvent, mais cela renvoie une position relative rendant plus difficile la détermination des pièces sélectionnées. (Pas impossible, je sais, mais cela semble inutilement compliqué).

Edit: C’est le code que j’ai utilisé pour essayer d’obtenir la taille du conteneur de stockage, selon l’une des questions. TableLayout est la table qui contient toutes les pièces du puzzle.

TableLayout tableLayout = (TableLayout) findViewById(R.id.tableLayout);
Log.d(LOG_TAG, "Values " + tableLayout.getTop() + tableLayout.getLeft());

Edit 2: Voici le code que j'ai essayé en suivant plusieurs des réponses suggérées.

public int[] tableLayoutCorners = new int[2];
(...)

TableLayout tableLayout = (TableLayout) findViewById(R.id.tableLayout);
tableLayout.requestLayout();
Rect corners = new Rect();
tableLayout.getLocalVisibleRect(corners);
Log.d(LOG_TAG, "Top left " + corners.top + ", " + corners.left + ", " + corners.right
            + ", " + corners.bottom);

cells[4].getLocationOnScreen(tableLayoutCorners);
Log.d(LOG_TAG, "Values " + tableLayoutCorners[0] + ", " + tableLayoutCorners[1]);

Ce code a été ajouté une fois l’initialisation terminée. L'image a été divisée en un tableau de ImageViews (le tableau de cellules []) contenu dans un TableLayout. Les cellules [0] sont en haut à gauche ImageView, et j'ai choisi les cellules [4] car elles se situent quelque part au milieu et ne doivent absolument pas avoir les coordonnées de (0,0).

Le code ci-dessus me donne toujours tous les 0 dans les journaux, ce que je ne comprends vraiment pas car les différentes pièces du puzzle sont correctement affichées. (J'ai essayé int public pour tableLayoutCorners et la visibilité par défaut, les deux donnant le même résultat.)

Je ne sais pas si cela est significatif, mais les ImageViews ne sont pas à l'origine d'une taille. La taille de la ImageViews est déterminée lors de l'initialisation automatiquement par la vue lorsque je lui donne une image à afficher. Est-ce que cela pourrait contribuer à ce que leurs valeurs soient égales à 0, même si ce code de journalisation est après avoir reçu une image et s'être redimensionné automatiquement? Pour contrer potentiellement cela, j'ai ajouté le code tableLayout.requestLayout() comme indiqué ci-dessus, mais cela n'a pas aidé.

368
Steve Haley
588
Romain Guy

La réponse acceptée ne dit pas vraiment comment se rendre, alors voici un peu plus de détails. Vous transmettez un tableau int de longueur 2 et les valeurs sont remplacées par les coordonnées (x, y) de la vue (du coin supérieur gauche).

int[] location = new int[2];
myView.getLocationOnScreen(location);
int x = location[0];
int y = location[1];

Notes

  • Remplacer getLocationOnScreen par getLocationInWindow devrait donner les mêmes résultats dans la plupart des cas (voir cette réponse ). Cependant, si vous vous trouvez dans une fenêtre plus petite, comme un dialogue ou un clavier personnalisé, vous devrez choisir celle qui convient le mieux à vos besoins.
  • Vous obtiendrez (0,0) si vous appelez cette méthode dans onCreate car la vue n'a pas encore été affichée. Vous pouvez utiliser ViewTreeObserver pour savoir quand la mise en page est terminée et obtenir les coordonnées mesurées. (Voir cette réponse .)
100
Suragch

Vous devez d'abord obtenir le rectangle localVisible de la vue

Pour par exemple:

Rect rectf = new Rect();

//For coordinates location relative to the parent
anyView.getLocalVisibleRect(rectf);

//For coordinates location relative to the screen/display
anyView.getGlobalVisibleRect(rectf);

Log.d("WIDTH        :", String.valueOf(rectf.width()));
Log.d("HEIGHT       :", String.valueOf(rectf.height()));
Log.d("left         :", String.valueOf(rectf.left));
Log.d("right        :", String.valueOf(rectf.right));
Log.d("top          :", String.valueOf(rectf.top));
Log.d("bottom       :", String.valueOf(rectf.bottom));

J'espère que cela aidera

73
Naveen Murthy

L'utilisation d'un auditeur de disposition global a toujours bien fonctionné pour moi. Il présente l'avantage de pouvoir réévaluer des éléments si la présentation est modifiée, par exemple. si quelque chose est défini sur View.GONE ou des vues enfant sont ajoutées/supprimées.

public void onCreate(Bundle savedInstanceState)
{
     super.onCreate(savedInstanceState);

     // inflate your main layout here (use RelativeLayout or whatever your root ViewGroup type is
     LinearLayout mainLayout = (LinearLayout ) this.getLayoutInflater().inflate(R.layout.main, null); 

     // set a global layout listener which will be called when the layout pass is completed and the view is drawn
     mainLayout.getViewTreeObserver().addOnGlobalLayoutListener(
       new ViewTreeObserver.OnGlobalLayoutListener() {
          public void onGlobalLayout() {
               //Remove the listener before proceeding
               if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                    mainLayout.getViewTreeObserver().removeOnGlobalLayoutListener(this);
               } else {
                    mainLayout.getViewTreeObserver().removeGlobalOnLayoutListener(this);
               }

               // measure your views here
          }
       }
     );

     setContentView(mainLayout);
 }
45
Simon

Après le commentaire de Romain Guy, voici comment je l’ai corrigé. J'espère que cela aidera tout le monde qui a également eu ce problème.

J'essayais en effet de connaître la position des points de vue avant qu'ils ne soient affichés à l'écran, mais ce n'était pas du tout évident. Ces lignes avaient été placées après l'exécution du code d'initialisation, alors j'ai supposé que tout était prêt. Cependant, ce code était toujours dans onCreate (); en expérimentant avec Thread.sleep (), j'ai découvert que la mise en page n'était pas finalisée avant la fin de l'exécution de onCreate () jusqu'à onResume (). Donc, en effet, le code essayait de s'exécuter avant que la mise en page ait été positionnée à l'écran. En ajoutant le code à un OnClickListener (ou à un autre écouteur), les valeurs correctes ont été obtenues car il ne pouvait être déclenché qu'après la mise en page.


La ligne ci-dessous a été suggérée comme modification de communauté:

veuillez utiliser onWindowfocuschanged(boolean hasFocus)

17
Steve Haley

Première manière:

Dans Kotlin nous pouvons créer une simple extension pour la vue:

fun View.getLocationOnScreen(): Point
{
    val location = IntArray(2)
    this.getLocationOnScreen(location)
    return Point(location[0],location[1])
}

Et simplement obtenir les coordonnées:

val location = yourView.getLocationOnScreen()
val absX = location.x
val absY = location.y

Deuxième manière:

La deuxième façon est plus simple:

fun View.absX(): Int
{
    val location = IntArray(2)
    this.getLocationOnScreen(location)
    return location[0]
}

fun View.absY(): Int
{
    val location = IntArray(2)
    this.getLocationOnScreen(location)
    return location[1]
}

et obtenez simplement X absolu par view.absX() et Y par view.absY()

7

Mes utilitaires fonctionnent pour obtenir l'emplacement de la vue. Ils renverront un objet Point avec x value et y value.

public static Point getLocationOnScreen(View view){
    int[] location = new int[2];
    view.getLocationOnScreen(location);
    return new Point(location[0], location[1]);
}

En utilisant

Point viewALocation = getLocationOnScreen(viewA);
5
Phan Van Linh