ti-enxame.com

Obtendo coordenadas do View em relação ao layout raiz

Posso obter a posição x e y de uma vista em relação ao layout raiz da minha atividade no Android?

128
fhucho

Essa é uma solução, embora, como as APIs mudam com o tempo e possam existir outras maneiras de fazer isso, verifique as outras respostas. Um afirma ser mais rápido e outro afirma ser mais fácil.

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());
}

Deixe-me saber se isso funciona.

Ele deve recursivamente apenas adicionar as posições superior e esquerda de cada contêiner pai. Você também poderia implementá-lo com um Point, se quisesse.

132
ramblinjan

O Android API já fornece um método para conseguir isso. Tente isto:

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;

Aqui está o doc

115
carlo.marinangeli

Por favor use view.getLocationOnScreen(int[] location); (veja Javadocs ). A resposta está no array inteiro (x = location[0] e y = location[1]).

91
BinaryTofu

Não há necessidade de calculá-lo manualmente.

Apenas use getGlobalVisibleRect assim:

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

Observe também que para as coordenadas do centro, em vez de algo como:

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

Você pode apenas fazer:

float cx = myViewRect.exactCenterX();
float cy = myViewRect.exactCenterY();
34
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];

Primeiro, obtenho o layout raiz e, em seguida, calculo a diferença das coordenadas com a visão.
Você também pode usar a getLocationOnScreen() em vez de getLocationInWindow().

32
Kerrmiter

Você pode usar

view.getLocationOnScreen (localização int [])

; `para obter a localização da sua visualização corretamente.

Mas há um pegar se você usá-lo antes de o layout ter sido inflado, você terá uma posição errada.

Solução para este problema é adicionar ViewTreeObserver assim: -

Declare globalmente a matriz para armazenar a posição x y da sua visualização

 int[] img_coordinates = new int[2];

e, em seguida, adicione ViewTreeObserver no layout pai para obter retorno de chamada para a inflação do layout e só então buscar a posição da exibição senão você obterá coordenadas xy incorretas

  // 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);
                        }
                    }
            );

e depois usá-lo assim

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

Eu escrevi a mim mesmo dois métodos utilitários que parecem funcionar na maioria das condições, manuseando rolagem, tradução e escala, mas não rotação. Eu fiz isso depois de tentar usar offsetDescendantRectToMyCoords () na estrutura, que tinha precisão inconsistente. Funcionou em alguns casos, mas deu resultados errados em outros.

"point" é um array float com dois elementos (as coordenadas x e y), "ancestor" é um viewgroup em algum lugar acima do "descendente" na hierarquia da árvore.

Primeiro um método que vai de coordenadas descendentes para ancestral:

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);
    }
}

Em seguida o inverso, do ancestral ao descendente:

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
Alexander Hugestrand

Incase alguém ainda está tentando descobrir isso. É assim que você obtém o centro X e Y do view.

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

Acabei de encontrar a resposta aqui

Ele diz: É possível recuperar a localização de uma visão invocando os métodos getLeft () e getTop (). O primeiro retorna a coordenada esquerda, ou X, do retângulo representando a vista. O último retorna a coordenada superior ou Y do retângulo que representa a vista. Esses métodos retornam a localização da exibição em relação a seu pai. Por exemplo, quando getLeft () retorna 20, isso significa que a visualização está localizada a 20 pixels à direita da borda esquerda de seu pai direto.

então use:

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