web-dev-qa-db-ja.com

getLocationOnScreen()vs getLocationInWindow()

これら2つのメソッドのコンテキストでの画面とビューの違いは何ですか?

ボタンがあり、その中心のx座標を取得します。

これで十分だと思います:

_public int getButtonXPosition() {
    return (button.getLeft()+button.getRight())/2;
}
_

しかし、その後、私が使用した場合、それはどのような違いを生むでしょう

getLocationOnScreen()またはgetLocationInWindow()

(もちろん、ボタンの幅の半分を追加します)

63
Elad Benda

この答え が正しいとは思わない。新しいプロジェクトを作成し、次のスニペットを追加してMainActivityのみを編集した場合:

public boolean dispatchTouchEvent(MotionEvent ev) {
    View contentsView = findViewById(Android.R.id.content);

    int test1[] = new int[2];
    contentsView.getLocationInWindow(test1);

    int test2[] = new int[2];
    contentsView.getLocationOnScreen(test2);

    System.out.println(test1[1] + " " + test2[1]);

    return super.dispatchTouchEvent(ev);
}

コンソールに印刷されます108 108。これは、4.3を実行しているNexus 7を使用しています。 Android 2.2までのバージョンを実行しているエミュレータを使用して、同様の結果が得られました。

通常のアクティビティウィンドウは、WindowManager.LayoutParamsとしてFILL_PARENTxFILL_PARENTを持つため、画面全体のサイズにレイアウトされます。ウィンドウは(y座標ではなく、z座標に関して)ステータスバーとその他の装飾の下にレイアウトされているため、より正確なチャートは次のようになります。

|--phone screen-----activity window---| 
|--------status bar-------------------| 
|                                     | 
|                                     | 
|-------------------------------------| 

これらの2つのメソッドのソースをステップスルーすると、getLocationInWindowがビューのビュー階層をRootViewImplまで上に移動し、ビュー座標を合計して親スクロールオフセットを減算することがわかります。上記の場合、ViewRootImplはWindowSessionからステータスバーの高さを取得し、fitSystemWindowsを介してActionBarOverlayLayoutに渡します。これにより、この値がアクションバーの高さに追加されます。 ActionBarOverlayLayoutはこの合計値を取得し、レイアウトの親であるコンテンツビューにマージンとして適用します。

したがって、コンテンツは、ステータスバーよりも低いy座標で始まるウィンドウの結果ではなく、アクティビティのコンテンツビューにマージンが適用された結果として、ステータスバーより下にレイアウトされます。

getLocationOnScreenソースを覗くと、それは単にgetLocationInWindowを呼び出してから、ウィンドウの左と上の座標を追加します(ViewRootImplによってViewに渡され、ViewRootImplからそれらを取得します) WindowSession)。通常の場合、これらの値は両方ともゼロになります。画面の中央に配置されるダイアログウィンドウなど、これらの値がゼロ以外になる場合があります。


要約すると、通常のアクティビティのウィンドウは、ステータスバーや装飾の下のスペースも含めて画面全体に表示されます。問題の2つのメソッドは、同じxおよびy座標を返します。これらの2つの値は、ウィンドウが実際にオフセットされるダイアログなどの特別な場合にのみ異なります。

110
groucho

getLocationOnScreen()は、電話画面に基づいて位置を取得します。

getLocationInWindow()は、アクティビティウィンドウに基づいて位置を取得します。

通常のアクティビティ(フルスクリーンアクティビティではない)の場合、電話画面とアクティビティウィンドウとの関係は以下のとおりです。

| --電話画面 ------------------
| -----------(ステータスバー
------------------
| |
| ------------------------------------------- |
| -----------(アクティビティウィンドウ
------ ------- |
| |
| |
| |
| |
| |
| |
| ------------------------------------------- |

X座標の場合、両方のメソッドの値は通常同じです。

Y座標の場合、値にはステータスバーの高さの違いがあります

24
Ivan

現在受け入れられている答えは少し冗長です。ここに短いものがあります。

getLocationOnScreen()getLocationInWindow()は通常同じ値を返します。これは、ウィンドウが通常画面と同じサイズだからです。ただし、ウィンドウが画面よりも小さい場合があります。たとえば、Dialogまたはカスタムシステムキーボード。

したがって、必要な座標が常に画面に対して相対的であることがわかっている場合(通常のアクティビティのように)、getLocationOnScreen()を使用できます。ただし、ビューが画面よりも小さいウィンドウ(ダイアログやカスタムキーボードなど)にある場合は、getLocationInWindow()を使用します。

関連

4
Suragch