回答:
これは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
必要に応じて、それを実装することもできます。
Android APIには、そのための方法がすでに用意されています。これを試して:
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;
ここにドキュメントがあります
parentViewGroup
機能しました。それはビュー階層の任意の親になることができるので、ScrollViewでも完全に機能します。
使用してくださいview.getLocationOnScreen(int[] location);
(Javadocsを参照)。答えは整数配列(x = location[0]
およびy = location[1]
)にあります。
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()
。
手動で計算する必要はありません。
次のように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();
getGlobalVisibleRect
行うことはある globalOffset.set(-mScrollX, -mScrollY);
あなただけでそれらの値を得ることができるので、getScollX/Y
あなただけの相対による座標が必要な場合。
あなたは `を使うことができます
view.getLocationOnScreen(int [] location)
; `ビューの位置を正しく取得します。
しかし、落とし穴がありますレイアウトが間違った位置を取得します膨らませてきた前にあなたがそれを使用する場合。
この問題の解決策は ViewTreeObserver
ようにです:-
ビューのxy位置を格納する配列をグローバルに宣言します
int[] img_coordinates = new int[2];
次に追加します ViewTreeObserver
親レイアウトをして、レイアウトインフレーションのコールバックを取得し、ビューの位置をフェッチするだけです。そうしないと、間違ったxy座標が取得されます。
// 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];
私は、ほとんどの状況で動作するように見える2つのユーティリティメソッドを記述しました。スクロール、変換、スケーリングは処理しますが、回転は処理しません。フレームワークでoffsetDescendantRectToMyCoords()を使用しようとした後、これに一貫性のない精度がありました。それはいくつかのケースで機能しましたが、他のケースでは間違った結果を与えました。
"point"は2つの要素(x座標とy座標)を持つfloat配列で、 "ancestor"はツリー階層の "子孫"の上にあるビューグループです。
最初に、子孫座標から祖先に移動するメソッド:
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;
}
誰かがまだこれを理解しようとしている場合。これは、の中心XおよびYを取得する方法ですview
。
int pos[] = new int[2];
view.getLocationOnScreen(pos);
int centerX = pos[0] + view.getMeasuredWidth() / 2;
int centerY = pos[1] + view.getMeasuredHeight() / 2;
私はここで答えを見つけました
それは言う:メソッドgetLeft()とgetTop()を呼び出すことによってビューの場所を取得することが可能です。前者は、ビューを表す長方形の左またはX座標を返します。後者は、ビューを表す長方形の上部またはY座標を返します。これらのメソッドはどちらも、親を基準にしたビューの位置を返します。たとえば、getLeft()が20を返す場合、ビューはその直接の親の左端から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