ビューの絶対座標を取得する方法
-
19-09-2019 - |
質問
ビューの左上隅の絶対スクリーンピクセル座標を取得しようとしています。ただし、次のような私が見つけることができるすべての方法 getLeft()
そして getRight()
それらはすべてビューの親に相対しているように見えるため、機能しません。 0
. 。これを行う適切な方法は何ですか?
参考になれば、これは「写真を元の順序に戻す」ゲームです。ユーザーがボックスを描画して複数の部分を選択できるようにしたいと考えています。私の推測では、それを行う最も簡単な方法は次のとおりです getRawX()
そして getRawY()
から MotionEvent
次に、これらの値を、ピースを保持しているレイアウトの左上隅と比較します。ピースのサイズがわかれば、選択されたピースの数がわかります。使えることに気づきました getX()
そして getY()
で MotionEvent
, ただし、相対的な位置が返されるため、どの部分が選択されたかを判断するのがより困難になります。(不可能ではありませんが、不必要に複雑に思えます)。
編集:これは、質問の 1 つに従って、保持コンテナのサイズを取得するために使用したコードです。 TableLayout
すべてのパズルのピースが入っているテーブルです。
TableLayout tableLayout = (TableLayout) findViewById(R.id.tableLayout);
Log.d(LOG_TAG, "Values " + tableLayout.getTop() + tableLayout.getLeft());
編集2:これは、提案された回答に従って、私が試したコードです。
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]);
このコードは、すべての初期化が完了した後に追加されました。画像は、内に含まれる ImageView の配列 (cells[] 配列) に分割されています。 TableLayout
. 。Cells[0]は左上です ImageView
, そして、セル[4]を選択しました。セル[4]は中間のどこかにあり、間違いなく座標が (0,0) であってはいけないからです。
上記のコードでは、ログには依然としてすべて 0 が表示されますが、さまざまなパズルのピースが正しく表示されているため、これが本当に理解できません。(tableLayoutCorners とデフォルトの可視性に対して public int を試しましたが、どちらも同じ結果が得られました。)
これが重要かどうかはわかりませんが、 ImageView
にはもともとサイズが与えられていません。のサイズ ImageView
s は、表示する画像をビューに与えると、初期化中にビューによって自動的に決定されます。そのロギングコードが画像が与えられ、自動的にサイズ変更された後であるにもかかわらず、これが値が 0 になることに寄与しているのでしょうか?それに対抗するために、コードを追加しました tableLayout.requestLayout()
上に示したように、しかしそれは役に立ちませんでした。
解決
View.getLocationOnScreen()
に使用および/または getLocationInWindow()
するます。
他のヒント
受け入れられた回答では実際に場所を取得する方法が説明されていなかったので、ここでもう少し詳しく説明します。あなたは、 int
長さ 2 の配列であり、値はビューの (x, y) 座標 (上左隅の) に置き換えられます。
int[] location = new int[2];
myView.getLocationOnScreen(location);
int x = location[0];
int y = location[1];
ノート
- 交換中
getLocationOnScreen
とgetLocationInWindow
ほとんどの場合、同じ結果が得られるはずです (「 この答え)。ただし、ダイアログやカスタム キーボードなどの小さなウィンドウを使用している場合は、ニーズに合ったものを選択する必要があります。 - あなたは得ます
(0,0)
このメソッドを呼び出すとonCreate
ビューがまだ設定されていないためです。を使用できますViewTreeObserver
レイアウトが完了したときをリッスンして、測定された座標を取得できます。(見る この答え.)
まず、ビューのlocalVisible矩形を取得する必要があります。
例を示します。
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));
これが役立つことを願っています。
リスナーはいつも私のためによく働いている世界的なレイアウトを使用しました。それは、例えば、レイアウトが変更された場合のものを再測定することができるという利点を持っています何かがView.GONEまたは子ビューに設定されている場合、追加/削除されます。
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);
}
ロマン・ガイさんのコメントに続き、ここで私はそれを固定する方法です。うまくいけば、それはまた、この問題を抱えていた他の誰をお手伝いします。
私は確かに彼らは画面上にレイアウトされていた前のビューの位置を取得しようとしていたが、起こっていたことは全く明らかではなかったです。 initilisationコードが走った後にこれらの行が置かれていたので、私はすべての準備が整ったと想定しました。しかし、このコードはのonCreate()にまだありました。 Thread.sleep()を使って実験によって私はonResume(すべての方法)のレイアウトが実際のonCreate(後まで確定されていないことを発見した)実行を終了していました。だから、確かに、コードは、レイアウトが画面上に配置されて終わった前に実行しようとしていました。レイアウトが終了した後にのみ焼成することができるので、OnClickListener(またはいくつかの他のリスナー)にコードを追加することによって、正しい値が得られた。
<時間>以下のコミュニティ編集と示唆された行:
onWindowfocuschanged(boolean hasFocus)
を使用してください。
最初の方法:
で コトリン ビュー用の単純な拡張機能を作成できます。
fun View.getLocationOnScreen(): Point
{
val location = IntArray(2)
this.getLocationOnScreen(location)
return Point(location[0],location[1])
}
そして単純に座標を取得します。
val location = yourView.getLocationOnScreen()
val absX = location.x
val absY = location.y
2 番目の方法:
2 番目の方法はより簡単です。
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]
}
そして単に次のようにして絶対 X を取得します view.absX()
とYによる view.absY()
GETビューの場所のための私のutilsの機能、それはPoint
とx value
でy value
オブジェクトを返します。
public static Point getLocationOnScreen(View view){
int[] location = new int[2];
view.getLocationOnScreen(location);
return new Point(location[0], location[1]);
}
使用
Point viewALocation = getLocationOnScreen(viewA);
このコードを使用して、正確な X 座標と Y 座標を見つけます。
int[] array = new int[2];
ViewForWhichLocationIsToBeFound.getLocationOnScreen(array);
if (AppConstants.DEBUG)
Log.d(AppConstants.TAG, "array X = " + array[0] + ", Y = " + array[1]);
ViewWhichToBeMovedOnFoundLocation.setTranslationX(array[0] + 21);
ViewWhichToBeMovedOnFoundLocation.setTranslationY(array[1] - 165);
ビューを調整するためにいくつかの値を加算/減算しました。 これらの行は、ビュー全体が拡張された後にのみ実行してください。