Bagaimana cara mempertahankan Mode Imersif baru saat aktivitas saya menampilkan Dialog kustom?
Saya menggunakan kode di bawah ini untuk mempertahankan Mode Imersif dalam Dialog, tetapi dengan solusi itu, NavBar muncul kurang dari satu detik ketika saya memulai Dialog kustom saya, lalu menghilang.
Video berikut menjelaskan masalah dengan lebih baik (lihat bagian bawah layar saat NavBar muncul): http://youtu.be/epnd5ghey8g
Bagaimana cara menghindari perilaku ini?
KODE
Bapak dari semua aktivitas di aplikasi saya:
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();
}
}
Semua Dialog kustom saya memanggil metode ini dalam onCreate(. . .)
metode mereka :
/**
* 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 - SOLUSI (terima kasih kepada Beaver6813, lihat jawabannya untuk lebih jelasnya):
Semua dialog khusus saya menggantikan metode pertunjukan dengan cara ini:
/**
* 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);
}
Jawaban:
Setelah banyak penelitian tentang masalah ini, ada perbaikan hacky untuk ini, yang melibatkan merobek kelas Dialog untuk menemukan. Bilah navigasi ditampilkan saat jendela dialog ditambahkan ke Pengelola Jendela meskipun Anda menyetel visibilitas UI sebelum menambahkannya ke pengelola. Dalam contoh Android Immersive dikomentari bahwa:
Saya yakin itulah yang kami lihat di sini (bahwa interaksi pengguna dipicu saat tampilan jendela baru yang dapat difokuskan ditambahkan ke pengelola).
Bagaimana kita bisa mengatasi ini? Jadikan Dialog tidak dapat difokuskan saat kita membuatnya (agar kita tidak memicu interaksi pengguna), lalu membuatnya dapat difokuskan setelah ditampilkan.
Jelas ini tidak ideal tetapi tampaknya merupakan bug Android, mereka harus memeriksa apakah Jendela memiliki set yang imersif.
Saya telah memperbarui kode uji kerja saya (maafkan kekacauan yang diretas) ke Github . Saya telah menguji emulator Nexus 5, itu mungkin akan meledak dengan sesuatu yang kurang dari KitKat tetapi hanya untuk pembuktian konsep.
sumber
Untuk informasi Anda, terima kasih atas jawaban @ Beaver6813, saya bisa membuatnya bekerja menggunakan DialogFragment.
dalam metode onCreateView dari DialogFragment saya, saya baru saja menambahkan yang berikut ini:
sumber
Jika Anda ingin menggunakan onCreateDialog () , coba kelas ini. Ini bekerja dengan cukup baik untuk saya ...
Untuk menampilkan dialog, lakukan hal berikut dalam aktivitas Anda ...
sumber
Menggabungkan jawaban di sini saya membuat kelas abstrak yang berfungsi di semua kasus:
sumber
Ini juga bekerja pada metode onDismiss dari fragmen dialog Anda. Dan di dalam metode itu panggil metode aktivitas tempat ia dilampirkan lagi setel tanda layar penuh.
Dan dalam aktivitas Anda tambahkan metode ini:
sumber
AlertDialog.Builder
dan.setOnDismissListener()
Saat Anda membuat DialogFragment Anda sendiri, Anda hanya perlu mengganti metode ini.
sumber
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
dialog setelah yang ditampilkanSaya tahu ini posting lama, tetapi jawaban saya mungkin membantu orang lain.
Di bawah ini adalah perbaikan hacky untuk efek Immersive dalam Dialog:
sumber