Last updated on: May 27, 2023
In this tutorial, I’m going to show you how to fix your app, when an Android 10 (or above) device uses Gesture Navigation, with some examples
Instead of the classic 2-3 button navigation bar, with the gesture navigation, we have to make some changes to look more beautiful.
Contents
Preparing the device/emulator for testing
Device
If you have an Android 10 device (or above) with a notch and you don’t have the Gesture navigation enabled, go to Settings > System > Gestures > System navigation and choose Gesture navigation
Emulator
Create a new emulator with Android Q (API 29) or above, choose Pixel 3 XL (or whatever pixel with a notch you like), and check the box Enable Device Frame.
Detecting if the Gesture Navigation is enabled
First, we need to detect when an Android 10 user has the Gesture navigation enabled.
To do that, we read the user’s settings system navigation option
private fun isGestureNavigationEnabled(): Boolean {
val defaultNavigationMode = 0
val gestureNavigationMode = 2
return Settings.Secure.getInt(contentResolver, "navigation_mode", defaultNavigationMode) == gestureNavigationMode
}
Code language: Kotlin (kotlin)
…and we use it like that:
if (isGestureNavigationEnabled()) {
// Gesture Navigation is Enabled
} else {
// 2-3 Buttons Navigation Bar is Enabled
}
Code language: Swift (swift)
Please note that some users have reported that this method may not be the most secure way to detect it, as different devices may have varying numbers of gesture navigations. Unfortunately, Google has not yet provided a solution for this issue.
Fixing Full-Screen Activity
If you have a Full-Screen Activity and you wish to expand it across the entire screen:
class FullScreenActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_full_screen)
// ...
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && isGestureNavigationEnabled()) {
configureFullScreenMode()
}
}
@RequiresApi(Build.VERSION_CODES.Q)
private fun configureFullScreenMode() {
// Extends the PhotoView in the whole screen
window.addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS)
// Hides StatusBar and Navigation bar, you have to tap to appear
// window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_IMMERSIVE or View.SYSTEM_UI_FLAG_FULLSCREEN or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
// Fixes the Full Screen black bar in screens with notch
window.attributes.layoutInDisplayCutoutMode =
WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
}
private fun isGestureNavigationEnabled(): Boolean {
// Default navigation mode value
val defaultNavigationMode = 0
val gestureNavigationMode = 2
return Settings.Secure.getInt(contentResolver, "navigation_mode", defaultNavigationMode) == gestureNavigationMode
}
}
Code language: Kotlin (kotlin)
Fixing Activity with RecyclerView
In an Activity with Views, like RecyclerView, you want to expand the RecyclerView under the Gesture Navigation Bar and avoid hiding the last item.
class RecyclerViewActivity : AppCompatActivity() {
private var itemsArray = ArrayList<String>()
private lateinit var adapter: RVAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_recycler_view)
val recyclerView = findViewById<RecyclerView>(R.id.recycler_view)
val recyclerViewContentId = findViewById<RelativeLayout>(R.id.recycler_view_content_id)
// ...
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && isGestureNavigationEnabled()) {
extendBackgroundUnderNavigationBar(recyclerView, recyclerViewContentId)
}
}
// ...
private fun extendBackgroundUnderNavigationBar(
recyclerView: RecyclerView,
recyclerViewContentId: RelativeLayout
) {
// Disable clipping of the RecyclerView content when we use padding
recyclerView.clipToPadding = false
// Make the Gesture Navigation Bar transparent
window.navigationBarColor = Color.TRANSPARENT
// Expand the Views (RecyclerView) under the gesture navigation bar and toolbar
window.decorView.systemUiVisibility =
(View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_LAYOUT_STABLE)
// Set padding for the Views (RecyclerView and Relative Layout) from the System Views (Gesture Navigation Bar, Toolbar)
recyclerViewContentId.setOnApplyWindowInsetsListener { _, insets ->
val topPadding = insets.systemWindowInsetTop
val bottomPadding = insets.systemWindowInsetBottom
recyclerViewContentId.setPadding(0, topPadding, 0, 0)
recyclerView.setPadding(0, 0, 0, bottomPadding)
insets.consumeSystemWindowInsets()
}
}
private fun isGestureNavigationEnabled(): Boolean {
val defaultNavigationMode = 0
val gestureNavigationMode = 2
return Settings.Secure.getInt(contentResolver, "navigation_mode", defaultNavigationMode) == gestureNavigationMode
}
// ...
}
Code language: Kotlin (kotlin)
You can find the final project here
If you have any questions, please feel free to leave a comment below