ビューの左上隅の絶対スクリーンピクセル座標を取得しようとしています。しかし、getLeft()
やgetRight()
のような私が見つけることができるすべてのメソッドは、ビューの親に対して相対的であるように見えるので動作しません。したがって、私は0
を与えます。これを行うための適切な方法は何ですか?
それが助けになるならば、これは「写真を元に戻す」ゲームのためのものです。複数の部分を選択するためのボックスを描くことができるようにしたいです。これを行う最も簡単な方法は、MotionEvent
からgetRawX()
とgetRawY()
を選び、それらの値をレイアウトを保持しているレイアウトの左上隅と比較することです。ピースのサイズがわかれば、選択したピースの数を判断できます。私はMotionEvent
でgetX()
とgetY()
を使うことができることに気づきました、しかしそれはどの部分が選ばれたか決定することをより困難にする相対位置を返す。 (不可能ではない、私は知っているが、それは不必要に複雑に思える)。
編集:これは私が質問の一つとして、保持コンテナのサイズを取得しようとするために使用したコードです。 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]);
このコードは、すべての初期化が完了した後に追加されました。画像はTableLayout
内に含まれるImageViewの配列(cells []配列)に分割されています。 Cells [0]は左上のImageView
です、そして私はcells [4]を中央のどこかにあるので選びました。そして間違いなく(0,0)の座標を持つべきではありません。
上記のコードでは、ログに0が表示されていますが、さまざまなパズルのピースが正しく表示されているため、理解できません。 (私は、tableLayoutCornersとデフォルトの可視性に対してpublic intを試しましたが、どちらも同じ結果になりました。)
これが重要かどうかはわかりませんが、ImageView
には元々サイズが指定されていません。 ImageView
sのサイズは、表示する画像を指定すると、Viewによって初期化中に自動的に決定されます。ロギングコードにイメージが与えられ、自動的に自分自身のサイズを変更した後であっても、これは値が0になるのに役立ちますか?潜在的にそれに対抗するために、上記のようにコードtableLayout.requestLayout()
を追加しましたが、それは役に立ちませんでした。
View.getLocationOnScreen()
および/または getLocationInWindow()
を使用します。
受け入れられた答えは実際には場所を取得する方法を教えてくれなかったので、ここでもう少し詳しく説明します。長さ2のint
配列を渡すと、値はビューの(x、y)座標(上左上隅の座標)に置き換えられます。
int[] location = new int[2];
myView.getLocationOnScreen(location);
int x = location[0];
int y = location[1];
注
getLocationOnScreen
を getLocationInWindow
に置き換えても、ほとんどの場合同じ結果が得られます(を参照)。 この答え )。しかし、Dialogやカスタムキーボードのように小さなウィンドウを開いている場合は、用途に合わせてどちらを選択する必要がありますか。onCreate
でこのメソッドを呼び出すと(0,0)
が返されます。 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);
}
Romain Guyのコメントに続いて、これを修正しました。うまくいけば、それはまたこの問題を抱えていた他の誰かを助けるでしょう。
私はビューがスクリーンにレイアウトされる前にビューの位置を取得しようとしていましたが、それが起こっていることはまったく明白ではありませんでした。これらの行は初期化コードが実行された後に配置されていたので、すべてが準備できたと思いました。しかし、このコードはまだonCreate()にありました。 Thread.sleep()を試してみると、onCreate()からonResume()までのすべての実行が終了するまで、レイアウトは実際には確定されないことがわかりました。つまり、レイアウトが画面上に配置される前にコードが実行されようとしていました。 OnClickListener(または他の何らかのListener)にコードを追加することによって、レイアウトが終了した後にのみ発生する可能性があるため、正しい値が取得されました。
以下の行はコミュニティ編集として提案されました:
onWindowfocuschanged(boolean hasFocus)
を使ってください
ビューの場所を取得するための私のutils関数、それはx value
とy value
でPoint
オブジェクトを返します
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);
最初の方法:
Kotlinでは、単純な拡張子のビューを作成できます。
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]
}
そして単にview.absX()
で絶対Xを、そしてview.absY()
で絶対Yを得る