web-dev-qa-db-fra.com

Obtenir les coordonnées de la vue par rapport à la mise en page racine

Puis-je obtenir la position x et y d'une vue par rapport à la disposition racine de mon activité sur Android?

129
fhucho

Il s’agit d’une solution. Toutefois, étant donné que les API changent avec le temps et qu’il peut exister d’autres méthodes, veillez à vérifier les autres réponses. L'un prétend être plus rapide et l'autre, plus facile.

private int getRelativeLeft(View myView) {
    if (myView.getParent() == myView.getRootView())
        return myView.getLeft();
    else
        return myView.getLeft() + getRelativeLeft((View) myView.getParent());
}

private int getRelativeTop(View myView) {
    if (myView.getParent() == myView.getRootView())
        return myView.getTop();
    else
        return myView.getTop() + getRelativeTop((View) myView.getParent());
}

Faites-moi savoir si cela fonctionne.

Il faut simplement récursivement ajouter les positions haut et gauche de chaque conteneur parent. Vous pouvez également l'implémenter avec un Point si vous le souhaitez.

131
ramblinjan

L’API Android fournit déjà une méthode pour y parvenir. Essayez ceci:

Rect offsetViewBounds = new Rect();
//returns the visible bounds
childView.getDrawingRect(offsetViewBounds);
// calculates the relative coordinates to the parent
parentViewGroup.offsetDescendantRectToMyCoords(childView, offsetViewBounds); 

int relativeTop = offsetViewBounds.top;
int relativeLeft = offsetViewBounds.left;

Voici le doc

121
carlo.marinangeli

Veuillez utiliser view.getLocationOnScreen(int[] location); (voir Javadocs ). La réponse est dans le tableau entier (x = location[0] et y = location[1]).

91
BinaryTofu

Pas besoin de le calculer manuellement.

Utilisez simplement getGlobalVisibleRect comme ceci:

Rect myViewRect = new Rect();
myView.getGlobalVisibleRect(myViewRect);
float x = myViewRect.left;
float y = myViewRect.top;

Notez également que pour les coordonnées du centre, plutôt que quelque chose comme:

...
float two = (float) 2
float cx = myViewRect.left + myView.getWidth() / two;
float cy = myViewRect.top + myView.getHeight() / two;

Vous pouvez juste faire:

float cx = myViewRect.exactCenterX();
float cy = myViewRect.exactCenterY();
35
TalL
View rootLayout = view.getRootView().findViewById(Android.R.id.content);

int[] viewLocation = new int[2]; 
view.getLocationInWindow(viewLocation);

int[] rootLocation = new int[2];
rootLayout.getLocationInWindow(rootLocation);

int relativeLeft = viewLocation[0] - rootLocation[0];
int relativeTop  = viewLocation[1] - rootLocation[1];

Je commence par obtenir la disposition de la racine, puis je calcule la différence de coordonnées avec la vue.
Vous pouvez également utiliser getLocationOnScreen() au lieu de getLocationInWindow().

32
Kerrmiter

Vous pouvez utiliser `

view.getLocationOnScreen (int [] location)

; `pour obtenir l’emplacement de votre vue correctement.

Mais il y a un capture si vous l'utilisez avant que la disposition ne soit gonflée, vous obtiendrez une mauvaise position.

La solution à ce problème consiste à ajouter ViewTreeObserver comme ceci: -

Déclarer globalement le tableau pour stocker la position x y de votre vue

 int[] img_coordinates = new int[2];

puis ajoutez ViewTreeObserver sur votre mise en page parent pour obtenir un rappel pour l’inflation de la mise en page et ensuite seulement chercher la position de vue sinon vous obtiendrez de mauvaises coordonnées x y

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

                            // measure your views here
                            fab.getLocationOnScreen(img_coordinates);
                        }
                    }
            );

et ensuite l'utiliser comme ça

xposition = img_coordinates[0];
yposition =  img_coordinates[1];
6
Hitesh Sahu

J'ai moi-même écrit deux méthodes utilitaires qui semblent fonctionner dans la plupart des conditions: gestion du défilement, de la traduction et de la mise à l'échelle, mais pas de la rotation. Je l'ai fait après avoir essayé d'utiliser offsetDescendantRectToMyCoords () dans le cadre, qui présentait une précision incohérente. Cela a fonctionné dans certains cas mais a donné des résultats erronés dans d'autres.

"point" est un tableau flottant avec deux éléments (les coordonnées x et y), "ancêtre" est un groupe de vues situé quelque part au-dessus du "descendant" dans la hiérarchie de l'arbre.

D'abord une méthode qui va des coordonnées descendantes à l'ancêtre:

public static void transformToAncestor(float[] point, final View ancestor, final View descendant) {
    final float scrollX = descendant.getScrollX();
    final float scrollY = descendant.getScrollY();
    final float left = descendant.getLeft();
    final float top = descendant.getTop();
    final float px = descendant.getPivotX();
    final float py = descendant.getPivotY();
    final float tx = descendant.getTranslationX();
    final float ty = descendant.getTranslationY();
    final float sx = descendant.getScaleX();
    final float sy = descendant.getScaleY();

    point[0] = left + px + (point[0] - px) * sx + tx - scrollX;
    point[1] = top + py + (point[1] - py) * sy + ty - scrollY;

    ViewParent parent = descendant.getParent();
    if (descendant != ancestor && parent != ancestor && parent instanceof View) {
        transformToAncestor(point, ancestor, (View) parent);
    }
}

Ensuite l'inverse, de l'ancêtre au descendant:

public static void transformToDescendant(float[] point, final View ancestor, final View descendant) {
    ViewParent parent = descendant.getParent();
    if (descendant != ancestor && parent != ancestor && parent instanceof View) {
        transformToDescendant(point, ancestor, (View) parent);
    }

    final float scrollX = descendant.getScrollX();
    final float scrollY = descendant.getScrollY();
    final float left = descendant.getLeft();
    final float top = descendant.getTop();
    final float px = descendant.getPivotX();
    final float py = descendant.getPivotY();
    final float tx = descendant.getTranslationX();
    final float ty = descendant.getTranslationY();
    final float sx = descendant.getScaleX();
    final float sy = descendant.getScaleY();

    point[0] = px + (point[0] + scrollX - left - tx - px) / sx;
    point[1] = py + (point[1] + scrollY - top - ty - py) / sy;
}
2

Incase quelqu'un essaie toujours de comprendre cela. Voici comment vous obtenez le centre X et Y du view.

    int pos[] = new int[2];
    view.getLocationOnScreen(pos);
    int centerX = pos[0] + view.getMeasuredWidth() / 2;
    int centerY = pos[1] + view.getMeasuredHeight() / 2;
1

Je viens de trouver la réponse ici

Il dit: Il est possible de récupérer l'emplacement d'une vue en appelant les méthodes getLeft () et getTop (). Le premier retourne la coordonnée gauche ou X du rectangle représentant la vue. Ce dernier renvoie la coordonnée supérieure ou Y du rectangle représentant la vue. Ces méthodes renvoient à la fois l'emplacement de la vue par rapport à son parent. Par exemple, lorsque getLeft () renvoie 20, cela signifie que la vue est située à 20 pixels à droite du bord gauche de son parent direct.

alors utilisez:

view.getLeft(); // to get the location of X from left to right
view.getRight()+; // to get the location of Y from right to left
1
donmj