■ getLocationInWindow(int[] location)
ウィンドウ上でのこの View の位置を計算します。引数は長さが2以上の int 配列で、Index 0 に x 座標、Index 1 に y 座標の値が入ります。
http://tools.oesf.biz/android-4.0.1_r1.0/xref/frameworks/base/core/java/android/view/View.java#12047
- 12047 public void getLocationInWindow(int[] location) {
- 12048 if (location == null || location.length < 2) {
- 12049 throw new IllegalArgumentException("location must be an array of "
- 12050 + "two integers");
- 12051 }
- 12052
- 12053 location[0] = mLeft;
- 12054 location[1] = mTop;
- 12055 if (mTransformationInfo != null) {
- 12056 location[0] += (int) (mTransformationInfo.mTranslationX + 0.5f);
- 12057 location[1] += (int) (mTransformationInfo.mTranslationY + 0.5f);
- 12058 }
- 12059
- 12060 ViewParent viewParent = mParent;
- 12061 while (viewParent instanceof View) {
- 12062 final View view = (View)viewParent;
- 12063 location[0] += view.mLeft - view.mScrollX;
- 12064 location[1] += view.mTop - view.mScrollY;
- 12065 if (view.mTransformationInfo != null) {
- 12066 location[0] += (int) (view.mTransformationInfo.mTranslationX + 0.5f);
- 12067 location[1] += (int) (view.mTransformationInfo.mTranslationY + 0.5f);
- 12068 }
- 12069 viewParent = view.mParent;
- 12070 }
- 12071
- 12072 if (viewParent instanceof ViewRootImpl) {
- 12073 // *cough*
- 12074 final ViewRootImpl vr = (ViewRootImpl)viewParent;
- 12075 location[1] -= vr.mCurScrollY;
- 12076 }
- 12077 }
例えば、次のような画面のボタンに対して呼び出すと
- final int[] anchorPos = new int[2];
- v.getLocationOnScreen(anchorPos);
- Log.d(TAG, "position : " + v.getLeft() + ", " + v.getTop());
- Log.d(TAG, "window location : " + anchorPos[0] + ", " + anchorPos[1] );
window location : 0, 146
となりますが、translationX をセットすると
- v.setTranslationX(100);
- final int[] anchorPos = new int[2];
- v.getLocationOnScreen(anchorPos);
- Log.d(TAG, "position : " + v.getLeft() + ", " + v.getTop());
- Log.d(TAG, "window location : " + anchorPos[0] + ", " + anchorPos[1] );
window location : 100, 146
となります。translationX は getLeft() には影響しません。
mParent をたどって、View の親 ViewGroup の左上の位置とスクロール位置と Translation を考慮するので、例えば次のように ScrollView の中にいれたとすると
最初の状態では
window location : 0, 746
ですが、スクロールするとその分だけ y の位置が変わります。
window location : 0, 488
■ getLocationOnScreen(int[] location)
スクリーン上でのこの View の位置を計算します。引数は長さが2以上の int 配列で、Index 0 に x 座標、Index 1 に y 座標の値が入ります。
http://tools.oesf.biz/android-4.0.1_r1.0/xref/frameworks/base/core/java/android/view/View.java#12030
- 12030 public void getLocationOnScreen(int[] location) {
- 12031 getLocationInWindow(location);
- 12032
- 12033 final AttachInfo info = mAttachInfo;
- 12034 if (info != null) {
- 12035 location[0] += info.mWindowLeft;
- 12036 location[1] += info.mWindowTop;
- 12037 }
- 12038 }
getLocationInWindow() と getLocationOnScreen() が異なる例として、ダイアログがあります。
例えばこの Activity のテーマを Theme.Holo.Light.Dialog にしてみます。
そうすると、次のように値が異なります。
window location : 16, 148
screen location : 56, 635
getLocationInWindow() はダイアログからの相対位置、getLocationOnScreen() は画面上の位置になります。
もちろん Dialog クラスを使ったダイアログ上の View でも同じです。
■ getWindowVisibleDisplayFrame(Rect outRect)
このメソッドは上の2つとはちょっと違って、このビューが配置されているウィンドウのサイズを取得します。
実質的にはこのコンテンツ(View)が配置できかつユーザーから見える領域になります。
引数で渡した Rect の top, bottom, left, right に値が格納されます。
http://tools.oesf.biz/android-4.0.1_r1.0/xref/frameworks/base/core/java/android/view/View.java#5825
- 5825 public void getWindowVisibleDisplayFrame(Rect outRect) {
- 5826 if (mAttachInfo != null) {
- 5827 try {
- 5828 mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
- 5829 } catch (RemoteException e) {
- 5830 return;
- 5831 }
- 5832 // XXX This is really broken, and probably all needs to be done
- 5833 // in the window manager, and we need to know more about whether
- 5834 // we want the area behind or in front of the IME.
- 5835 final Rect insets = mAttachInfo.mVisibleInsets;
- 5836 outRect.left += insets.left;
- 5837 outRect.top += insets.top;
- 5838 outRect.right -= insets.right;
- 5839 outRect.bottom -= insets.bottom;
- 5840 return;
- 5841 }
- 5842 Display d = WindowManagerImpl.getDefault().getDefaultDisplay();
- 5843 d.getRectSize(outRect);
- 5844 }
dispalyFrame : 0, 50, 720, 1184
(left, top, right, bottom)
となります。ステータスバーやナビゲーションバーは入らない(View を配置できない)ということです。
一方、次のように Toast にセットしたビューに対して取得すると
dispalyFrame : 0, 0, 720, 1184
(left, top, right, bottom)
となり、ステータスバーの領域も含まれます。
これは Toast を表示する Window のレイヤーが Activity の setContentView() で表示される View とは異なるからです。
- Toast toast = Toast.makeText(MainActivity.this, "Hello World", Toast.LENGTH_SHORT);
- toast.setGravity(Gravity.TOP, 0, 0);
- toast.show();
- toast.getView().getWindowVisibleDisplayFrame(displayFrame);
また、IME 部分は含まれません。そのため、IME を表示した状態と表示していない状態では値がかわります。
表示していない状態
dispalyFrame : 0, 50, 720, 1184
(left, top, right, bottom)
表示している状態
dispalyFrame : 0, 50, 720, 604
(left, top, right, bottom)
ちなみに DisplayMetrics の値は
widthPixels : 720
heightPixels : 1184
でステータスバーは入りますが、ナビゲーションバーは入りません(ナビゲーションバーの高さは 48dip * 2 = 96px)。
■ getGlobalVisibleRect(Rect r)
この View の可視領域を global (root) の座標で返します。 getLocationInWindow() と同じように親の ViewGroup の位置、スクロール、Translation が考慮されます。
■ getDrawingRect(Rect outRect)
この View の可視描画領域を返します。 親の ViewGroup の位置、スクロール、Translation は考慮されません。
0 件のコメント:
コメントを投稿