1. ホーム
  2. android

[解決済み] ダイアログで没入型モードを維持するには?

2022-10-08 14:26:39

質問

アクティビティがカスタムダイアログを表示するとき、新しい没入型モードを維持するにはどうしたらよいでしょうか。

私はダイアログで没入型モードを維持するために以下のコードを使用していますが、このソリューションでは、カスタムダイアログを開始すると、ナビバーが1秒未満表示され、その後消えます。

次の動画は、この問題をよりよく説明しています (NavBar が表示されたときに画面の下部を見ます)。 http://youtu.be/epnd5ghey8g

この動作を回避するにはどうすればよいですか?

CODE

私のアプリケーションのすべてのアクティビティの父です。

public abstract class ImmersiveActivity extends Activity {

    @SuppressLint("NewApi")
    private void disableImmersiveMode() {
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
            getWindow().getDecorView().setSystemUiVisibility(
                    View.SYSTEM_UI_FLAG_FULLSCREEN
            );
        }
    }

    @SuppressLint("NewApi")
    private void enableImmersiveMode() {
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
            getWindow().getDecorView().setSystemUiVisibility(
                      View.SYSTEM_UI_FLAG_LAYOUT_STABLE 
                    | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION 
                    | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN 
                    | View.SYSTEM_UI_FLAG_FULLSCREEN 
                    | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY 
                    | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
            );
        }
    }


    /**
     * Set the Immersive mode or not according to its state in the settings:
     * enabled or not.
     */
    protected void updateSystemUiVisibility() {
        // Retrieve if the Immersive mode is enabled or not.
        boolean enabled = getSharedPreferences(Util.PREF_NAME, 0).getBoolean(
                "immersive_mode_enabled", true);

        if (enabled) enableImmersiveMode();
        else disableImmersiveMode();
    }

    @Override
    public void onResume() {
        super.onResume();
        updateSystemUiVisibility();
    }

    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
        updateSystemUiVisibility();
    }

}



私のカスタムダイアログはすべてこのメソッドを onCreate(. . .) メソッドで呼び出します。

/**
 * Copy the visibility of the Activity that has started the dialog {@link mActivity}. If the
 * activity is in Immersive mode the dialog will be in Immersive mode too and vice versa.
 */
@SuppressLint("NewApi")
private void copySystemUiVisibility() {
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
        getWindow().getDecorView().setSystemUiVisibility(
                mActivity.getWindow().getDecorView().getSystemUiVisibility()
        );
    }
}



EDIT - THE SOLUTION (Beaver6813に感謝します。詳細は彼の回答を見てください) :

私のカスタムダイアログはすべてこの方法でshowメソッドをオーバーライドしています。

/**
 * An hack used to show the dialogs in Immersive Mode (that is with the NavBar hidden). To
 * obtain this, the method makes the dialog not focusable before showing it, change the UI
 * visibility of the window like the owner activity of the dialog and then (after showing it)
 * makes the dialog focusable again.
 */
@Override
public void show() {
    // Set the dialog to not focusable.
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
            WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);

    copySystemUiVisibility();

    // Show the dialog with NavBar hidden.
    super.show();

    // Set the dialog to focusable again.
    getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
}

どのように解決するのですか?

この問題についていろいろと調査した結果、この問題を解決するための簡単な方法がありました。 ダイアログ クラスを解体して見つけました。ダイアログ ウィンドウをウィンドウ マネージャに追加する前に UI の可視性を設定しても、ウィンドウ マネージャに追加されるとナビゲーション バーが表示されます。その際 Android Immersive の例 とコメントされています。

// * Uses semi-transparent bars for the nav and status bars
// * This UI flag will *not* be cleared when the user interacts with the UI.
// When the user swipes, the bars will temporarily appear for a few seconds and then
// disappear again.

これがここで見ているものだと思います(新しい、フォーカス可能な、ウィンドウビューがマネージャに追加されたときに、ユーザーインタラクションがトリガーされること)。

どのようにこれを回避することができますか? ダイアログを作成するときに非フォーカス可能にし (ユーザー インタラクションをトリガーしないように)、表示後にフォーカス可能にすることができます。

//Here's the magic..
//Set the dialog to not focusable (makes navigation ignore us adding the window)
dialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);

//Show the dialog!
dialog.show();

//Set the dialog to immersive
dialog.getWindow().getDecorView().setSystemUiVisibility(
context.getWindow().getDecorView().getSystemUiVisibility());

//Clear the not focusable flag from the window
dialog.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);

これは明らかに理想的ではありませんが、Android のバグであるようです。

私は作業中のテスト コードを更新しました (雑なのはご容赦ください)。 Github . Nexus 5 エミュレータでテストしましたが、KitKat 未満ではおそらく吹き飛ばされます。