Background
It's possible to have the navigation bar to be transparent, so that content will be drawn behind it (in Z coordinate) and that there will be views above it (in Y coordinate), like on the camera app:
For the Camera app, there is content behind the navigation bar (the camera preview), and there are views above it (the buttons)
The problem
Every solution I've found (and there are many, such as here) doesn't let me the choice of having both transparent navigation bar while having views above it and behind it.
What I've tried
Here's one way I tried to solve it, using android:fitsSystemWindows="true"
(sample here):
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
window.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS)
setContentView(R.layout.activity_main)
}
}
activity_main.xml
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content" android:background="#33ff0000"
android:text="text behind nav bar"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"/>
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content" android:background="#3300ff00"
android:text="text above nav bar" android:fitsSystemWindows="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
</android.support.constraint.ConstraintLayout>
styles.xml
<resources>
<style name="AppTheme" parent="Theme.AppCompat.NoActionBar">
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="android:windowFullscreen">true</item>
</style>
</resources>
But the result is that both views are behind the navigation bar :
The only way I've found that works, is to get the height of the navigation bar, and set the bottom margin of the view to be with this value, but this seems like a weird solution, which I'd like to try to avoid :
/**
* returns the natural orientation of the device: Configuration.ORIENTATION_LANDSCAPE or Configuration.ORIENTATION_PORTRAIT .<br></br>
* The result should be consistent no matter the orientation of the device
*/
fun getScreenNaturalOrientation(context: Context): Int {
with(context) {
//based on : http://stackoverflow.com/a/9888357/878126
val windowManager = getSystemService(Context.WINDOW_SERVICE) as WindowManager
val config = resources.configuration
val rotation = windowManager.defaultDisplay.rotation
return if ((rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180) && config.orientation == Configuration.ORIENTATION_LANDSCAPE || (rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270) && config.orientation == Configuration.ORIENTATION_PORTRAIT)
Configuration.ORIENTATION_LANDSCAPE
else
Configuration.ORIENTATION_PORTRAIT
}
}
fun getNavBarHeight(context: Context, defaultHeightToReturn: Int = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 48f, context.resources.displayMetrics).toInt()): Int {
val resources = context.resources
val orientation = resources.configuration.orientation
val isTablet = getScreenNaturalOrientation(context) == Configuration.ORIENTATION_LANDSCAPE
val resourceId = if (isTablet)
resources.getIdentifier(if (orientation == Configuration.ORIENTATION_PORTRAIT) "navigation_bar_height" else "navigation_bar_height_landscape", "dimen", "android")
else
resources.getIdentifier(if (orientation == Configuration.ORIENTATION_PORTRAIT) "navigation_bar_height" else "navigation_bar_width", "dimen", "android")
if (resourceId > 0) {
return resources.getDimensionPixelSize(resourceId)
}
return defaultHeightToReturn
}
The questions
How come it ignores
android:fitsSystemWindows
?How can I make one view above the navigation bar and one behind it, like on the camera app ? I also don't want that on old Android versions there will be extra space for no reason.
EDIT: about why android:fitsSystemWindows
doesn't work, I've found this and this. However, when I tried to use this technique by just having a CoordinatorLayout
, it still didn't work on the above case:
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".MainActivity" android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content" android:background="#33ff0000"
android:text="text behind nav bar" android:textSize="20sp" android:layout_gravity="bottom"
/>
<TextView android:layout_width="wrap_content" android:textSize="20sp" android:layout_gravity="bottom|end"
android:layout_height="wrap_content" android:background="#3300ff00"
android:text="text above nav bar" android:fitsSystemWindows="true"
/>
</android.support.design.widget.CoordinatorLayout>
You can make the background of the navigation bar same as the background of your activity that would make it appear as a transparent.