web-dev-qa-db-ja.com

ルートレイアウトに対するビューの座標の取得

Androidのアクティビティのルートレイアウトに対するビューのxおよびy位置を取得できますか?

129
fhucho

これは1つのソリューションです。ただし、APIは時間とともに変化するため、他の方法もありますので、必ず他の回答を確認してください。 1つはより高速であると主張し、もう1つはより簡単であると主張します。

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

それが機能するかどうか教えてください。

各親コンテナーから上と左の位置を再帰的に追加するだけです。必要に応じて、Pointを使用して実装することもできます。

131
ramblinjan

Android AP​​Iは、それを実現するメソッドをすでに提供しています。これを試して:

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;

これが doc です

121

view.getLocationOnScreen(int[] location);を使用してください( Javadocs を参照)。答えは整数配列です(x = location[0]およびy = location[1])。

91
BinaryTofu

手動で計算する必要はありません。

getGlobalVisibleRect を使用してください:

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

また、次のようなものではなく、中心座標についても注意してください。

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

あなたはただすることができます:

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];

最初にルートレイアウトを取得してから、ビューとの座標差を計算します。
getLocationOnScreen()の代わりにgetLocationInWindow()を使用することもできます。

32
Kerrmiter

あなたは `を使用することができます

view.getLocationOnScreen(int [] location)

; `ビューの位置を正しく取得します。

ただし、catchがあります。レイアウトが膨張する前に使用すると、間違った位置になります。

この問題の解決策は、次のようにViewTreeObserverを追加しています:-

ビューのx y位置を格納する配列をグローバルに宣言します

 int[] img_coordinates = new int[2];

次に、親レイアウトにViewTreeObserverを追加してレイアウトインフレーションのコールバックを取得し、ビューの位置を取得しますそれ以外の場合は、間違った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);
                        }
                    }
            );

そして、このように使用します

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

ほとんどの状況で機能するように見える2つのユーティリティメソッドを作成しました。スクロール、変換、スケーリングを処理しますが、回転はしません。フレームワークでoffsetDescendantRectToMyCoords()を使用してみましたが、これは一貫性のない精度でした。場合によっては機能しましたが、他では間違った結果をもたらしました。

「ポイント」は2つの要素(xおよびy座標)を持つ浮動小数点配列で、「祖先」はツリー階層の「子孫」の上のビューグループです。

まず、子孫座標から祖先に移動するメソッド:

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

次に、祖先から子孫への逆:

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

誰かがまだこれを理解しようとしている場合。これは、viewの中心のXとYを取得する方法です。

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

私はちょうど答えを見つけました ここ

メソッド:getLeft()およびgetTop()を呼び出すことにより、ビューの場所を取得することができます。前者は、ビューを表す長方形の左またはX座標を返します。後者は、ビューを表す長方形の上部またはY座標を返します。これらのメソッドは両方とも、その親に対するビューの位置を返します。たとえば、getLeft()が20を返す場合、ビューは直接の親の左Edgeの右側20ピクセルに位置することを意味します。

使用する:

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