[解決済み] ダイアログで没入型モードを維持するには?
質問
アクティビティがカスタムダイアログを表示するとき、新しい没入型モードを維持するにはどうしたらよいでしょうか。
私はダイアログで没入型モードを維持するために以下のコードを使用していますが、このソリューションでは、カスタムダイアログを開始すると、ナビバーが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 未満ではおそらく吹き飛ばされます。
関連
-
[解決済み] Androidのソフトキーボードをプログラムで閉じる/隠すにはどうすればよいですか?
-
[解決済み] Androidでアクティビティ起動時にEditTextにフォーカスが当たらないようにする方法
-
[解決済み] インスタンス状態の保存を使用してアクティビティ状態を保存するにはどうすればよいですか?
-
[解決済み] Androidアプリケーションのアクティビティ間でデータを受け渡すにはどうすればよいですか?
-
[解決済み】「px」、「dip」、「dp」、「sp」の違いは?
-
[解決済み】プログレスダイアログとバックグラウンドスレッドがアクティブなときに、画面の向きが変わるのをどう処理するか?
-
[解決済み] AndroidにおけるViewPager2の適切な実装
-
[解決済み] Nexus 4でUSBデバッグモードを見つける方法とオンにする方法
-
[解決済み] ArrayList<MyCustomClass>をJSONArrayに変換する。
-
[解決済み] google-services.jsonって実際何してるの?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] HttpPostによる画像送信
-
[解決済み] AndroidでラジオボタンにOnClickListenerを設定するには?
-
[解決済み] データベースでリサイクルビューを使用する
-
[解決済み] アンドロイドのクライアントでヒープアップデートを有効にする方法
-
[解決済み] アンドロイドのdatepickerダイアログで最大の日付を設定するには?
-
[解決済み] TextView.setTextSizeの挙動がおかしい - テキストビューのテキストサイズを画面ごとに動的に設定する方法
-
[解決済み] PendingIntentの "requestCode "は何に使うのですか?
-
[解決済み] BottomNavigationViewを新しいNavControllerで使用する際に、フラグメントを生かす方法はありますか?
-
[解決済み] FABアイコンの色を設定する
-
[解決済み] google-services.jsonって実際何してるの?