Single Activity with Fullscreen & Simple Fragments

Single Activity
Recently Google have suggested that it’s better to use single activity for your applications. But what if your designer say that one UI should be on fullscreen, while another in simple mode, without drawing over status bar. Then for resolving this issue we will create one more Activity for Fullscreen and one Activity with Fragments for simple UI.
But with the help of Window insets you can easily do it on Fragments too and avoid using Activities and keep using Single Activity pattern.
systemUiVisibility
For rescuing us systemUiVisibility has been implemented. For setting UI visibility we have:
SYSTEM_UI_FLAG_VISIBLE, SYSTEM_UI_FLAG_LOW_PROFILE, SYSTEM_UI_FLAG_HIDE_NAVIGATION, SYSTEM_UI_FLAG_FULLSCREEN, SYSTEM_UI_FLAG_LAYOUT_STABLE, SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN, SYSTEM_UI_FLAG_IMMERSIVE, SYSTEM_UI_FLAG_IMMERSIVE_STICKY, SYSTEM_UI_FLAG_LIGHT_STATUS_BAR, SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR, SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
From these flags we only use two of them SYSTEM_UI_FLAG_LAYOUT_STABLE SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
For applying fullscreen mode within the app we need to apply it for our Single Activity then all our fragments will be in fullscreen mode, for this we have to call decorView’s setSystemUiVisiblity in our Activity
window?.apply {
decorView.systemUiVisibility =
View.SYSTEM_UI_FLAG_LAYOUT_STABLE or
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
var flags: Int = decorView.systemUiVisibility
flags = flags or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
decorView.systemUiVisibility = flags
}
navigationBarColor = Color.WHITE
}
If you can see I’ve implemented SYSTEM_UI_FLAG_LIGHT_STATUS_BAR too, this flag is responsible for coloring our status bar into light mode (default is black).
If we run our app we will get such result

As you can see we do not achieved fullscreen after applying systemUiVisibility on decorView, all because of our app have White color as colorPrimaryDark in colors.xml. All we need is to set Transparent status bar onResume in Fragment and return to white onDestroy for exiting from Fullscreen when Fullscreen Fragment has been closed.
override fun onResume() {
super.onResume()
activity?.window?.statusBarColor = Color.TRANSPARENT
}
override fun onDestroy() {
super.onDestroy()
activity?.window?.statusBarColor = Color.WHITE
}
After applying transparent status bar we will get our fullscreen

What if we open SimpleFragment

As you can see our image in simple fragment was clipped by status bar and for resolving this issue Window insets come to save us. Inside onViewCreated of Fragment we will listen for
view.setOnApplyWindowInsetsListener { v, insets ->
v.updatePadding(top = insets.systemWindowInsetTop)
insets
}
This function will be invoked when System wants to draw something over our view, something is status bar and navigation bar. System says us to set padding for our view in order to avoid clipping. Also we need to call
if (view.isAttachedToWindow) {
ViewCompat.requestApplyInsets(view)
} else {
view.addOnAttachStateChangeListener(object : View.OnAttachStateChangeListener {
override fun onViewAttachedToWindow(v: View) {
v.removeOnAttachStateChangeListener(this)
ViewCompat.requestApplyInsets(v)
}
override fun onViewDetachedFromWindow(v: View) = Unit
})
}
because sometimes window insets doesn’t invoked and we have to call it manually and our setOnApplyWindowInsetsListener will be invoked
After applying such padding from top we will get result which we have expected

Finally we have got our Simple and Fullscreen mode working as expected.
There is also an issue with navigation bar, some devices have navigation bar some doesn’t. If you want to avoid overdrawing on navigation bar use bottom padding in your view in v.updatePadding inside setOnApplyWindowInsetsListener. Or if you want to overdraw set Transparent color to navigation bar with navigationBarColor inside window in activity.
For more information about Window insets I really suggest you to watch Chris Banes “Becoming a master window fitter” on youtube https://www.youtube.com/watch?v=_mGDMVRO3iE