I'm using Immersive Mode in my app when it's running on Android 4.4+. (http://developer.android.com/training/system-ui/immersive.html)
My activity indeed shows in full screen, and I work around the volume key pressing by using setOnSystemUiVisibilityChangeListener
. I also have similar code for putting dialogs into immersive mode.
However, when a dialog is shown, the nav. bars jump on the screen and then retreat immediately. When the dialog is dismissed it's even worse - the nav. bars jump and resize the activity behind.
The following is my class for supporting immersive mode. It is simply called on each Activity's onResume and also a separate function is called when building each dialog.
Did I miss any flag or callback, or is it a known Android issue?
public class ImmersiveModeHelper {
public ImmersiveModeHelper(Activity activity)
{
mActivity = activity;
}
@SuppressLint("NewApi")
public void supportFullScreenImmersiveMode()
{
MyLog.d("ImmersiveModeHelper: supportFullScreenImmersiveMode: ");
// Support full-screen immersive mode on Android 4.4 and up
if (Build.VERSION.SDK_INT >= 19)
{
// Get the needed flags by reflection and use them
try
{
final int immersiveFlag = View.class.getField("SYSTEM_UI_FLAG_IMMERSIVE_STICKY")
.getInt(null);
final int hideNavigationFlag = View.class
.getField("SYSTEM_UI_FLAG_HIDE_NAVIGATION").getInt(null);
final int fullScreenFlag = View.class.getField("SYSTEM_UI_FLAG_FULLSCREEN").getInt(
null);
// Set the flags to the window decor view
mActivity.getWindow().getDecorView()
.setSystemUiVisibility(immersiveFlag | hideNavigationFlag | fullScreenFlag);
// Set a callback to be called when visibility changes
// (workaround
// for volume keys)
mActivity
.getWindow()
.getDecorView()
.setOnSystemUiVisibilityChangeListener(
new View.OnSystemUiVisibilityChangeListener()
{
@Override
public void onSystemUiVisibilityChange(int visibility)
{
MyLog.d("ImmersiveModeHelper.supportFullScreenImmersiveMode().new OnSystemUiVisibilityChangeListener() {...}: onSystemUiVisibilityChange: " +
"");
if ((visibility & (immersiveFlag | hideNavigationFlag)) == 0)
{
Handler uiHandler = UiThreadUtils.getUiHandler();
uiHandler.removeCallbacks(mHideSystemUiCallback);
uiHandler.postDelayed(mHideSystemUiCallback,
HIDE_SYSTEM_UI_DELAY_MILLI);
}
}
});
} catch (Exception e)
{
e.printStackTrace();
MyLog.e("ImmersiveModeHelper: supportFullScreenImmersiveMode: couldn't support immersive mode by reflection");
}
} else
{
MyLog.i("ImmersiveModeHelper: supportFullScreenImmersiveMode: not supported on this platform version");
}
}
public static void supportFullScreenImmersiveModeForDialog(final Dialog dlg)
{
MyLog.d("ImmersiveModeHelper: supportFullScreenImmersiveModeForDialog: ");
// Support full-screen immersive mode on Android 4.4 and up
if (Build.VERSION.SDK_INT >= 19)
{
final Window dlgWindow = dlg.getWindow();
// Get the needed flags by reflection and use them
try
{
final int immersiveFlag = View.class.getField("SYSTEM_UI_FLAG_IMMERSIVE_STICKY")
.getInt(null);
final int hideNavigationFlag = View.class
.getField("SYSTEM_UI_FLAG_HIDE_NAVIGATION").getInt(null);
final int fullScreenFlag = View.class.getField("SYSTEM_UI_FLAG_FULLSCREEN").getInt(
null);
// Set the flags to the window decor view
int flags = dlgWindow.getDecorView().getSystemUiVisibility();
flags |= (immersiveFlag | hideNavigationFlag | fullScreenFlag);
dlgWindow.getDecorView().setSystemUiVisibility(flags);
// Set a callback to be called when visibility changes
// (workaround for volume keys)
dlgWindow.getDecorView().setOnSystemUiVisibilityChangeListener(
new View.OnSystemUiVisibilityChangeListener()
{
@Override
public void onSystemUiVisibilityChange(int visibility)
{
MyLog.d("ImmersiveModeHelper.supportFullScreenImmersiveModeForDialog(...).new OnSystemUiVisibilityChangeListener() {...}: onSystemUiVisibilityChange: ");
if ((visibility & (immersiveFlag | hideNavigationFlag)) == 0)
{
Runnable hideSystemUiCallback = new Runnable()
{
@Override
public void run()
{
supportFullScreenImmersiveModeForDialog(dlg);
}
};
Handler uiHandler = UiThreadUtils.getUiHandler();
uiHandler.removeCallbacks(hideSystemUiCallback);
uiHandler.postDelayed(hideSystemUiCallback,
HIDE_SYSTEM_UI_DELAY_MILLI);
}
}
});
} catch (Exception e)
{
e.printStackTrace();
MyLog.e("ImmersiveModeHelper: supportFullScreenImmersiveMode: couldn't support immersive mode by reflection");
}
} else
{
MyLog.i("ImmersiveModeHelper: supportFullScreenImmersiveMode: not supported on this platform version");
}
}
private Activity mActivity;
private Runnable mHideSystemUiCallback = new Runnable()
{
@Override
public void run()
{
supportFullScreenImmersiveMode();
}
};
private static final int HIDE_SYSTEM_UI_DELAY_MILLI = 0;
}