2017年10月2日月曜日

Androidの画面回転で気になったこと

画面の回転がロックされていなければ、端末の画面の方向が切り替わるとActivityも回転後の画面に合わせて切り替わります。

Android 3.2(API レベル 13)以降ではActivitiyに
android:configChanges="orientation|screenSize"
が設定されていればActivityはイベントを受け取り画面サイズの変更に伴う必要な処理を行うことが要求される。

この指定がない場合AndroidがActivityを再作成して適切なユーザビリティを保とうとする。
この考え方はオブジェクト指向の考えでは消極的な実装で、さまざまなリソースの浪費を伴う。設計思想によるが、個人的にこの考え方は正直嫌い。しかし、Androidの思想は根底にこの考え方があるために、リッチな環境になればなるほど端末性能の高機能化が必要になった。と愚痴はこの辺で(笑)

今回問題になったのは、android:configChangesを指定しない場合、再作成のタイミングがAndroid側の歩み寄りにより、前提条件がそろえば再作成されないことがある。

一般的に再作成される条件は、画面の回転を行ったときに、画面の解像度の縦横比が変わったり、縦横の画素数が変わったときに行われる。

結果として、180度回転を行ったとき、Activityは再作成されず、画面が回転するアニメーションが実行されるだけとなる。
おそらくだが、正方形のディスプレイで解像度も正方形であれば、画面回転をさせてもまったく再作成されなくなるだろう。

一般的なアプリでは180度回転が行われて再作成されなくても影響はほぼ出ないだろう。

ただ、タッチディスプレイのイベント処理の最中。具体的には画面に触れている間に画面回転が行われた場合、再作成されなくなるとタッチ情報を引き継いでそのまま画面回転後にイベントの処理が行われる。

この、気の利かないAndroidの親切は正直に閉口するしかなかった。

単純に画面の回転を知るために、センサーイベントリスナを定義し、実装することも可能。実際に行って対応してみたが、タッチイベント処理の細工も必要となってしまった。

不必要なセンサーの監視やリスナが増えることによって不要な処理が増えてしまうという最悪の実装になってしまったのでここでアプローチを変えるということを考えた。

今まではアプリで画面回転を許可していた。その理由はAndroid 4.1の端末では全画面モードにしたとしてもどう足掻こうともナビゲーションバーを消すことができない。
表示上消したとしても端末のタッチ操作をした瞬間表示されてしまう。

そのためにどうしても画面を180度回転させてでもその領域のタッチ情報が必要だったためにこのような実装にしていた。

しかし、先日前提条件が変わって能動的に切り替えも実装できるようになったため今度は逆に起動時の画面の状態を把握する必要が出てきた。

画面が縦か横かという判断は単純に
getResources().getConfiguration().orientation
で取得できる。
ただ、これだけでは縦か横かは判断できるものの、上下の関係が分からないために正しく
setRequestedOrientation()
で画面を固定化させることができない。

getWindowManager().getDefaultDisplay().getRotation() で回転方向を知ることで正しく設定できると考えた。
実際にonCreateで画面回転を90度単位で行いログに吐き出させてみた。
10-02 20:44:30.370 18776-18776/com.example.siriu.orientationtest D/MainActivity: getRequestedOrientation():-1 Configuration:1 Rotation:0
10-02 20:44:35.863 18776-18776/com.example.siriu.orientationtest D/MainActivity: getRequestedOrientation():-1 Configuration:2 Rotation:1
10-02 20:44:40.011 18776-18776/com.example.siriu.orientationtest D/MainActivity: getRequestedOrientation():-1 Configuration:1 Rotation:2
10-02 20:44:42.962 18776-18776/com.example.siriu.orientationtest D/MainActivity: getRequestedOrientation():-1 Configuration:2 Rotation:3
;

rotationが0~3で取得され、Configurationで縦か横かきれいに取得できた。

上記は7インチタブレットの物だが、スマホだとこの組み合わせ…縦横が逆になるような気がする…。ならないかな?

まぁなんだろうか、縦か横かはconfigurationで決定し、rotationが2か3だったら逆転していると判断しておけば問題はなさそう。

ということで、起動時にこの値を取得し、Activityを固定化すれば再作成されることも、違和感なく、画面回転をロックすることができるだろう。

というかしてくれ(涙)

0 件のコメント:

コメントを投稿