マル開発日記

マルAndroidデベロッパ

View.getGlobalVisibleRectのRectはスクリーン座標じゃない

 AndroidのViewクラスにgetGlobalVisibleRectというメソッドあります。これで得られるRectはスクリーン座標系、いわゆるMotionEvent.getRawX(またはgetRawY)に対応するような座標系なのかと今まで思っていましたがどうやら違ってました。

 Android7(Nougat)のマルチウィンドウ機能で、例えば下ウィンドウにアプリを表示してこのメソッドを呼び出した場合、Rectはスクリーン座標系になってくれませんでした。

 じゃぁ、スクリーン座標系のRectを得るにはどうしたら良いか。。自分はとりあえず次のようにしてみました。

 

  int[ ] viewInWindow = new int[2];

  int[ ] viewOnScreen = new int[2];

  int[ ] windowOnScreen = new int[2];

  view.getLocationInWindow(viewInWindow);

  view.getLocationOnScreen(viewOnScreen);

  windowOnScreen[0] = viewOnScreen[0] - viewInWindow[0];

  windowOnScreen[1] = viewOnScreen[1] - viewInWindow[1];

  Rect r = new Rect();

  view.getGlobalVisibleRect(r));

  r.offset(windowOnScreen[0], windowOnScreen[1]);

 

 結構おマヌケな方法です。Windowクラスとかでウィンドウのスクリーンを基準にした座標を得るAPIないかなって探したけど見つからなかった。ViewクラスのgetLocationOnScreenを見ると、インナークラスであるAttachInfoのmWindowLeft, mWindowTopがウィンドウのスクリーン位置かなぁって分かるけど、この値をダイレクトに取る方法がない。パッケージアクセスしかできず、パブリックなゲッターも存在しないようなので。

 で、もう引き算すりゃいいやって考えになったけど、もっといい方法ないかなぁ。あっ、リフレクションとかは無しで。proguardとかではまりそうだから。