スポンサーリンク

2016年4月30日土曜日

Android Immersive モードを使ってみた

Android 4.4でImmersiveモードがサポートされました。これは画面上部のシステムバーや下部のナビゲーションバーを隠してフルスクリーンをアプリで使えるようにするものです。日本語に訳すと「没入モード」や「没頭モード」ということになりますが、今一つしっくりこないのでImmersiveモードで通します。

最近ではこのモードを使うアプリも増えてきました。アプリを初めて起動した時、以下の様なメッセージが表示されるのを見たことがある人も多いでしょう。



メッセージにある様にシステムバー、ナビゲーションバーを表示するには画面の上端から下(または下端から上)へ向かってスワイプします。



設定方法

設定するコードはだいたい以下の様なかんじになります。

        if (Build.VERSION.SDK_INT >= 19) {
            Window window = getWindow();
            View view = window.getDecorView();
            view.setSystemUiVisibility(
                View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY |
                    View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
                    View.SYSTEM_UI_FLAG_FULLSCREEN);
        }

View#setSystemUiVisibility() で次の何れかのフラグを設定します。

  • SYSTEM_UI_FLAG_IMMERSIVE
  • SYSTEM_UI_FLAG_IMMERSIVE_STICKY 


SYSTEM_UI_FLAG_IMMERSIVE は一度のユーザスワイプでImmersiveが解除されます。一方SYSTEM_UI_FLAG_IMMERSIVE_STICKYの方はスワイプで一時的にシステムバー、ナビゲーションバーが表示されますが、用が済めば再度非表示になります。

またこれらのフラグは SYSTEM_UI_FLAG_HIDE_NAVIGATION、SYSTEM_UI_FLAG_FULLSCREEN のどちらか、または両方と一緒に使った場合のみ効果があります。

さて上のコードでもそうですが、多くのサンプルコードでは DecoreView に対して setSystemUiVisivility() を設定しています。因みに DecoreView とは、ビューツリーの最上位にあり、Window に直接接続されているViewのことです。あまり馴染みがないかもしれません。

Immersiveモードを設定するのは必ずしもこのDecoreViewである必要はありません。表示されるViewのどれでも構いません。末端のViewに設定してもDecoreViewまで伝搬されて、最終的にWindowに対してImmersiveモードが設定されます。


ダイアログを表示すると無効になってしまう

Immersiveモードを使ってみて残念だったのが、ちょっとしたことですぐにImmersiveモードから抜けてしまうことです。例えばダイアログを表示しただけで無効になってしまいます。ダイアログから抜けるのにBackキーを使うやり方もあるので、これはこれでアリかとも思いますが、ダイアログを終了しても元に戻らないのです。

上にも書いたようにImmersiveモードはWindowに対して設定されます。ダイアログはActivityとは別のWindowを持つので、ダイアログを表示した瞬間に上下のバーが表示されてしまいます。

これには回避方法があります。ダイアログがフォーカスを持たないようにしてやれば良いのです。DialogFragmentであれば以下のコードで回避できます。


    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        Dialog dialog = getDialog();
        Window window = dialog.getWindow();
        window.addFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
    }


onCreateDialog() で設定しても構いませんが、Windowに対する設定は onActivityCreated() でやるのが確実です。

またフォーカスを持たないようにするのでキーイベントは取得できません。(タッチイベントは取得可能です。) ダイアログ上でキーイベントが必要な場合(テキストを入力するとか)は別の方法を考えなくてはなりません。

どこで設定するか

最後にどこで設定すべきか検討してみます。

Activity#onCreate() で設定すると一見うまくいっているように見えます。しかし一度ホーム画面を表示して、すぐにアプリに戻ってみて下さい。あれっ?Immersiveモードから抜けてしまいます。
ここはやはり Acrivity#onResume() で、表示直前に設定するのが確実ではないかと思います。



0 件のコメント :

コメントを投稿