OnApplyWindowInsetsListener gives systemWindowInsetBottom that is always 0












1















systemWindowInsetBottom AND stableInsetBottom are both always 0



I have an Activity, that has a background texture, and I am using FLAG_LAYOUT_NO_LIMITS to let that background go behind the status and navigation bar. But I don't want the other contents of the view to go behind those system UI components.



At first I thought of using resources.getIdentifier("navigation_bar_height", "dimen", "android") to get the height of the navigation bar, but that's just the default height of the navigation bar, so it won't work on devices where the user has hidden the navigation bar. (Samsung devices)



Then I found out about WindowInsets and android:fitsSystemWindows="true"



It works for the status bar, but it does not work for the navigation bar.



In my Activity



override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)

//These 2 flags don't seem to change anything
window.addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN)
window.addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR)
//This flag is required so the background can go behind the navbar
window.addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS)

rootView.setOnApplyWindowInsetsListener { _, insets ->
val topTextViewParams = rootView.tvTop.layoutParams as ViewGroup.MarginLayoutParams
topTextViewParams.topMargin = insets.systemWindowInsetTop

val bottomTextViewParams = rootView.tvBottom.layoutParams as ViewGroup.MarginLayoutParams
bottomTextViewParams.bottomMargin = insets.systemWindowInsetBottom //Inset is always 0

insets.consumeSystemWindowInsets()
}
}


And my layout



<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
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"
android:fitsSystemWindows="true"
android:id="@+id/rootView"
android:background="@color/colorPrimary"
tools:context=".MainActivity">

<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">

<TextView
android:id="@+id/tvBottom"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:text="Text aligned to bottom of layout with no margin"/>
<TextView
android:id="@+id/tvTop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:text="Text aligned to top of layout with no margin"/>
</android.support.constraint.ConstraintLayout>
</android.support.design.widget.CoordinatorLayout>


Example screenshots from Nexus 5x Emulator running API 28. Getting same results on my actual device running API 26.



Example Images



What do I have to do to get the actual size of the navigation bar, if it is present?










share|improve this question



























    1















    systemWindowInsetBottom AND stableInsetBottom are both always 0



    I have an Activity, that has a background texture, and I am using FLAG_LAYOUT_NO_LIMITS to let that background go behind the status and navigation bar. But I don't want the other contents of the view to go behind those system UI components.



    At first I thought of using resources.getIdentifier("navigation_bar_height", "dimen", "android") to get the height of the navigation bar, but that's just the default height of the navigation bar, so it won't work on devices where the user has hidden the navigation bar. (Samsung devices)



    Then I found out about WindowInsets and android:fitsSystemWindows="true"



    It works for the status bar, but it does not work for the navigation bar.



    In my Activity



    override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    //These 2 flags don't seem to change anything
    window.addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN)
    window.addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR)
    //This flag is required so the background can go behind the navbar
    window.addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS)

    rootView.setOnApplyWindowInsetsListener { _, insets ->
    val topTextViewParams = rootView.tvTop.layoutParams as ViewGroup.MarginLayoutParams
    topTextViewParams.topMargin = insets.systemWindowInsetTop

    val bottomTextViewParams = rootView.tvBottom.layoutParams as ViewGroup.MarginLayoutParams
    bottomTextViewParams.bottomMargin = insets.systemWindowInsetBottom //Inset is always 0

    insets.consumeSystemWindowInsets()
    }
    }


    And my layout



    <?xml version="1.0" encoding="utf-8"?>
    <android.support.design.widget.CoordinatorLayout
    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"
    android:fitsSystemWindows="true"
    android:id="@+id/rootView"
    android:background="@color/colorPrimary"
    tools:context=".MainActivity">

    <android.support.constraint.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
    android:id="@+id/tvBottom"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    android:text="Text aligned to bottom of layout with no margin"/>
    <TextView
    android:id="@+id/tvTop"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginStart="8dp"
    android:layout_marginEnd="8dp"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    android:text="Text aligned to top of layout with no margin"/>
    </android.support.constraint.ConstraintLayout>
    </android.support.design.widget.CoordinatorLayout>


    Example screenshots from Nexus 5x Emulator running API 28. Getting same results on my actual device running API 26.



    Example Images



    What do I have to do to get the actual size of the navigation bar, if it is present?










    share|improve this question

























      1












      1








      1








      systemWindowInsetBottom AND stableInsetBottom are both always 0



      I have an Activity, that has a background texture, and I am using FLAG_LAYOUT_NO_LIMITS to let that background go behind the status and navigation bar. But I don't want the other contents of the view to go behind those system UI components.



      At first I thought of using resources.getIdentifier("navigation_bar_height", "dimen", "android") to get the height of the navigation bar, but that's just the default height of the navigation bar, so it won't work on devices where the user has hidden the navigation bar. (Samsung devices)



      Then I found out about WindowInsets and android:fitsSystemWindows="true"



      It works for the status bar, but it does not work for the navigation bar.



      In my Activity



      override fun onCreate(savedInstanceState: Bundle?) {
      super.onCreate(savedInstanceState)
      setContentView(R.layout.activity_main)

      //These 2 flags don't seem to change anything
      window.addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN)
      window.addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR)
      //This flag is required so the background can go behind the navbar
      window.addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS)

      rootView.setOnApplyWindowInsetsListener { _, insets ->
      val topTextViewParams = rootView.tvTop.layoutParams as ViewGroup.MarginLayoutParams
      topTextViewParams.topMargin = insets.systemWindowInsetTop

      val bottomTextViewParams = rootView.tvBottom.layoutParams as ViewGroup.MarginLayoutParams
      bottomTextViewParams.bottomMargin = insets.systemWindowInsetBottom //Inset is always 0

      insets.consumeSystemWindowInsets()
      }
      }


      And my layout



      <?xml version="1.0" encoding="utf-8"?>
      <android.support.design.widget.CoordinatorLayout
      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"
      android:fitsSystemWindows="true"
      android:id="@+id/rootView"
      android:background="@color/colorPrimary"
      tools:context=".MainActivity">

      <android.support.constraint.ConstraintLayout
      android:layout_width="match_parent"
      android:layout_height="match_parent">

      <TextView
      android:id="@+id/tvBottom"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      app:layout_constraintBottom_toBottomOf="parent"
      app:layout_constraintLeft_toLeftOf="parent"
      app:layout_constraintRight_toRightOf="parent"
      android:text="Text aligned to bottom of layout with no margin"/>
      <TextView
      android:id="@+id/tvTop"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_marginStart="8dp"
      android:layout_marginEnd="8dp"
      app:layout_constraintTop_toTopOf="parent"
      app:layout_constraintStart_toStartOf="parent"
      app:layout_constraintEnd_toEndOf="parent"
      android:text="Text aligned to top of layout with no margin"/>
      </android.support.constraint.ConstraintLayout>
      </android.support.design.widget.CoordinatorLayout>


      Example screenshots from Nexus 5x Emulator running API 28. Getting same results on my actual device running API 26.



      Example Images



      What do I have to do to get the actual size of the navigation bar, if it is present?










      share|improve this question














      systemWindowInsetBottom AND stableInsetBottom are both always 0



      I have an Activity, that has a background texture, and I am using FLAG_LAYOUT_NO_LIMITS to let that background go behind the status and navigation bar. But I don't want the other contents of the view to go behind those system UI components.



      At first I thought of using resources.getIdentifier("navigation_bar_height", "dimen", "android") to get the height of the navigation bar, but that's just the default height of the navigation bar, so it won't work on devices where the user has hidden the navigation bar. (Samsung devices)



      Then I found out about WindowInsets and android:fitsSystemWindows="true"



      It works for the status bar, but it does not work for the navigation bar.



      In my Activity



      override fun onCreate(savedInstanceState: Bundle?) {
      super.onCreate(savedInstanceState)
      setContentView(R.layout.activity_main)

      //These 2 flags don't seem to change anything
      window.addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN)
      window.addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR)
      //This flag is required so the background can go behind the navbar
      window.addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS)

      rootView.setOnApplyWindowInsetsListener { _, insets ->
      val topTextViewParams = rootView.tvTop.layoutParams as ViewGroup.MarginLayoutParams
      topTextViewParams.topMargin = insets.systemWindowInsetTop

      val bottomTextViewParams = rootView.tvBottom.layoutParams as ViewGroup.MarginLayoutParams
      bottomTextViewParams.bottomMargin = insets.systemWindowInsetBottom //Inset is always 0

      insets.consumeSystemWindowInsets()
      }
      }


      And my layout



      <?xml version="1.0" encoding="utf-8"?>
      <android.support.design.widget.CoordinatorLayout
      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"
      android:fitsSystemWindows="true"
      android:id="@+id/rootView"
      android:background="@color/colorPrimary"
      tools:context=".MainActivity">

      <android.support.constraint.ConstraintLayout
      android:layout_width="match_parent"
      android:layout_height="match_parent">

      <TextView
      android:id="@+id/tvBottom"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      app:layout_constraintBottom_toBottomOf="parent"
      app:layout_constraintLeft_toLeftOf="parent"
      app:layout_constraintRight_toRightOf="parent"
      android:text="Text aligned to bottom of layout with no margin"/>
      <TextView
      android:id="@+id/tvTop"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_marginStart="8dp"
      android:layout_marginEnd="8dp"
      app:layout_constraintTop_toTopOf="parent"
      app:layout_constraintStart_toStartOf="parent"
      app:layout_constraintEnd_toEndOf="parent"
      android:text="Text aligned to top of layout with no margin"/>
      </android.support.constraint.ConstraintLayout>
      </android.support.design.widget.CoordinatorLayout>


      Example screenshots from Nexus 5x Emulator running API 28. Getting same results on my actual device running API 26.



      Example Images



      What do I have to do to get the actual size of the navigation bar, if it is present?







      android






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 25 '18 at 16:42









      lbenedettolbenedetto

      579316




      579316
























          2 Answers
          2






          active

          oldest

          votes


















          0














          I spend like 3 hours researching this before I posted and then 5 minutes after I posted.



          Those 5 minutes were very fruitful, because I found this post, which led me to try adding:



          <item name="android:windowTranslucentStatus">true</item>
          <item name="android:windowTranslucentNavigation">true</item>


          To my AppTheme, which worked.



          So, if you're trying to do this, make sure you:



          override fun onApplyWindowInsets(insets: WindowInsets): WindowInsets {
          val childCount = childCount
          for (index in 0 until childCount)
          getChildAt(index).dispatchApplyWindowInsets(insets)
          // let children know about WindowInsets

          return insets
          }


          OR

          Use a "materialish layout such as DrawerLayout or CoordinatorLayout" like I did in my post.



          Make sure to use android:fitsSystemWindows="true"



          Make sure to add those properties to your theme.



          And finally make to do something in your setOnApplyWindowInsetsListener






          share|improve this answer































            0














            Here's what I had to do to get both completely transparent status bar and navigation bar, with insets applied:



            My root view is a ContstraintLayout. Somehow it's working even without fitsSystemWindows and I'm getting the insets for both the top and bottom, which I've applied to my Toolbar and FrameLayout margins.



            In the theme:



            <item name="android:statusBarColor">@android:color/transparent</item>
            <item name="android:navigationBarColor">@android:color/transparent</item>
            <item name="android:windowTranslucentNavigation">false</item>
            <item name="android:windowTranslucentStatus">true</item>
            <item name="android:windowDrawsSystemBarBackgrounds">true</item>



            setImmersive function in Activity:



            I've created this function to apply the insets and window flags required to achieve the immersive look for a layout which can have:




            • Root view


              • Top view

              • Content

              • Bottom view




                /**
            * Apply immersive mode to this activity
            * @param rootView the root layout which will receive the window insets
            * @param topView the top view to apply insets to (optional)
            * @param bottomView the bottom view to apply insets to (optional)
            */
            fun setImmersive(rootView: ViewGroup, topView: View? = null, bottomView: View? = null) {

            window.addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS)

            rootView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
            bottomView?.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION

            rootView.setOnApplyWindowInsetsListener { _, insets ->
            Log.d(javaClass.simpleName + " windowInsets", insets.toString())

            // Apply the top insets
            if (topView != null) {
            insets.systemWindowInsetTop.apply {
            if (this > 0) {
            Log.d(javaClass.simpleName, "applying windowInsetTop $this")
            val layoutParams = topView.layoutParams as ViewGroup.MarginLayoutParams
            layoutParams.topMargin = this
            topView.layoutParams = layoutParams
            }
            }
            }

            // Apply the bottom insets
            if (bottomView != null) {
            insets.systemWindowInsetBottom.apply {
            if (this > 0) {
            Log.d(javaClass.simpleName, "applying windowInsetBottom $this")
            val layoutParams = bottomView.layoutParams as ViewGroup.MarginLayoutParams
            layoutParams.bottomMargin = this
            bottomView.layoutParams = layoutParams
            }
            }
            }

            insets.consumeSystemWindowInsets()
            }
            }


            Call this function in your onCreate eg.:



            override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.brand_activity)
            setImmersive(root_view, topView = toolbar, bottomView = root_content)
            }


            The OnApplyWindowInsetsListener on the root view was getting called twice, once with the correct insets WindowInsets{systemWindowInsets=Rect(0, 98 - 0, 168) and again with 0 insets WindowInsets{systemWindowInsets=Rect(0, 0 - 0, 0). So I'm only setting margins on the non-zero insets.



            In the layout:



            <androidx.constraintlayout.widget.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:id="@+id/root_view">

            <FrameLayout
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:id="@+id/root_content"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"/>

            <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/toolbar_layout"
            app:layout_constraintTop_toTopOf="parent">

            <androidx.appcompat.widget.Toolbar
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:id="@+id/toolbar">

            <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/toolbar_title"
            android:textStyle="bold"
            android:layout_gravity="center" />

            </androidx.appcompat.widget.Toolbar>
            </LinearLayout>
            </androidx.constraintlayout.widget.ConstraintLayout>





            share|improve this answer

























              Your Answer






              StackExchange.ifUsing("editor", function () {
              StackExchange.using("externalEditor", function () {
              StackExchange.using("snippets", function () {
              StackExchange.snippets.init();
              });
              });
              }, "code-snippets");

              StackExchange.ready(function() {
              var channelOptions = {
              tags: "".split(" "),
              id: "1"
              };
              initTagRenderer("".split(" "), "".split(" "), channelOptions);

              StackExchange.using("externalEditor", function() {
              // Have to fire editor after snippets, if snippets enabled
              if (StackExchange.settings.snippets.snippetsEnabled) {
              StackExchange.using("snippets", function() {
              createEditor();
              });
              }
              else {
              createEditor();
              }
              });

              function createEditor() {
              StackExchange.prepareEditor({
              heartbeatType: 'answer',
              autoActivateHeartbeat: false,
              convertImagesToLinks: true,
              noModals: true,
              showLowRepImageUploadWarning: true,
              reputationToPostImages: 10,
              bindNavPrevention: true,
              postfix: "",
              imageUploader: {
              brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
              contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
              allowUrls: true
              },
              onDemand: true,
              discardSelector: ".discard-answer"
              ,immediatelyShowMarkdownHelp:true
              });


              }
              });














              draft saved

              draft discarded


















              StackExchange.ready(
              function () {
              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53469643%2fonapplywindowinsetslistener-gives-systemwindowinsetbottom-that-is-always-0%23new-answer', 'question_page');
              }
              );

              Post as a guest















              Required, but never shown

























              2 Answers
              2






              active

              oldest

              votes








              2 Answers
              2






              active

              oldest

              votes









              active

              oldest

              votes






              active

              oldest

              votes









              0














              I spend like 3 hours researching this before I posted and then 5 minutes after I posted.



              Those 5 minutes were very fruitful, because I found this post, which led me to try adding:



              <item name="android:windowTranslucentStatus">true</item>
              <item name="android:windowTranslucentNavigation">true</item>


              To my AppTheme, which worked.



              So, if you're trying to do this, make sure you:



              override fun onApplyWindowInsets(insets: WindowInsets): WindowInsets {
              val childCount = childCount
              for (index in 0 until childCount)
              getChildAt(index).dispatchApplyWindowInsets(insets)
              // let children know about WindowInsets

              return insets
              }


              OR

              Use a "materialish layout such as DrawerLayout or CoordinatorLayout" like I did in my post.



              Make sure to use android:fitsSystemWindows="true"



              Make sure to add those properties to your theme.



              And finally make to do something in your setOnApplyWindowInsetsListener






              share|improve this answer




























                0














                I spend like 3 hours researching this before I posted and then 5 minutes after I posted.



                Those 5 minutes were very fruitful, because I found this post, which led me to try adding:



                <item name="android:windowTranslucentStatus">true</item>
                <item name="android:windowTranslucentNavigation">true</item>


                To my AppTheme, which worked.



                So, if you're trying to do this, make sure you:



                override fun onApplyWindowInsets(insets: WindowInsets): WindowInsets {
                val childCount = childCount
                for (index in 0 until childCount)
                getChildAt(index).dispatchApplyWindowInsets(insets)
                // let children know about WindowInsets

                return insets
                }


                OR

                Use a "materialish layout such as DrawerLayout or CoordinatorLayout" like I did in my post.



                Make sure to use android:fitsSystemWindows="true"



                Make sure to add those properties to your theme.



                And finally make to do something in your setOnApplyWindowInsetsListener






                share|improve this answer


























                  0












                  0








                  0







                  I spend like 3 hours researching this before I posted and then 5 minutes after I posted.



                  Those 5 minutes were very fruitful, because I found this post, which led me to try adding:



                  <item name="android:windowTranslucentStatus">true</item>
                  <item name="android:windowTranslucentNavigation">true</item>


                  To my AppTheme, which worked.



                  So, if you're trying to do this, make sure you:



                  override fun onApplyWindowInsets(insets: WindowInsets): WindowInsets {
                  val childCount = childCount
                  for (index in 0 until childCount)
                  getChildAt(index).dispatchApplyWindowInsets(insets)
                  // let children know about WindowInsets

                  return insets
                  }


                  OR

                  Use a "materialish layout such as DrawerLayout or CoordinatorLayout" like I did in my post.



                  Make sure to use android:fitsSystemWindows="true"



                  Make sure to add those properties to your theme.



                  And finally make to do something in your setOnApplyWindowInsetsListener






                  share|improve this answer













                  I spend like 3 hours researching this before I posted and then 5 minutes after I posted.



                  Those 5 minutes were very fruitful, because I found this post, which led me to try adding:



                  <item name="android:windowTranslucentStatus">true</item>
                  <item name="android:windowTranslucentNavigation">true</item>


                  To my AppTheme, which worked.



                  So, if you're trying to do this, make sure you:



                  override fun onApplyWindowInsets(insets: WindowInsets): WindowInsets {
                  val childCount = childCount
                  for (index in 0 until childCount)
                  getChildAt(index).dispatchApplyWindowInsets(insets)
                  // let children know about WindowInsets

                  return insets
                  }


                  OR

                  Use a "materialish layout such as DrawerLayout or CoordinatorLayout" like I did in my post.



                  Make sure to use android:fitsSystemWindows="true"



                  Make sure to add those properties to your theme.



                  And finally make to do something in your setOnApplyWindowInsetsListener







                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Nov 25 '18 at 16:54









                  lbenedettolbenedetto

                  579316




                  579316

























                      0














                      Here's what I had to do to get both completely transparent status bar and navigation bar, with insets applied:



                      My root view is a ContstraintLayout. Somehow it's working even without fitsSystemWindows and I'm getting the insets for both the top and bottom, which I've applied to my Toolbar and FrameLayout margins.



                      In the theme:



                      <item name="android:statusBarColor">@android:color/transparent</item>
                      <item name="android:navigationBarColor">@android:color/transparent</item>
                      <item name="android:windowTranslucentNavigation">false</item>
                      <item name="android:windowTranslucentStatus">true</item>
                      <item name="android:windowDrawsSystemBarBackgrounds">true</item>



                      setImmersive function in Activity:



                      I've created this function to apply the insets and window flags required to achieve the immersive look for a layout which can have:




                      • Root view


                        • Top view

                        • Content

                        • Bottom view




                          /**
                      * Apply immersive mode to this activity
                      * @param rootView the root layout which will receive the window insets
                      * @param topView the top view to apply insets to (optional)
                      * @param bottomView the bottom view to apply insets to (optional)
                      */
                      fun setImmersive(rootView: ViewGroup, topView: View? = null, bottomView: View? = null) {

                      window.addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS)

                      rootView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                      bottomView?.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION

                      rootView.setOnApplyWindowInsetsListener { _, insets ->
                      Log.d(javaClass.simpleName + " windowInsets", insets.toString())

                      // Apply the top insets
                      if (topView != null) {
                      insets.systemWindowInsetTop.apply {
                      if (this > 0) {
                      Log.d(javaClass.simpleName, "applying windowInsetTop $this")
                      val layoutParams = topView.layoutParams as ViewGroup.MarginLayoutParams
                      layoutParams.topMargin = this
                      topView.layoutParams = layoutParams
                      }
                      }
                      }

                      // Apply the bottom insets
                      if (bottomView != null) {
                      insets.systemWindowInsetBottom.apply {
                      if (this > 0) {
                      Log.d(javaClass.simpleName, "applying windowInsetBottom $this")
                      val layoutParams = bottomView.layoutParams as ViewGroup.MarginLayoutParams
                      layoutParams.bottomMargin = this
                      bottomView.layoutParams = layoutParams
                      }
                      }
                      }

                      insets.consumeSystemWindowInsets()
                      }
                      }


                      Call this function in your onCreate eg.:



                      override fun onCreate(savedInstanceState: Bundle?) {
                      super.onCreate(savedInstanceState)
                      setContentView(R.layout.brand_activity)
                      setImmersive(root_view, topView = toolbar, bottomView = root_content)
                      }


                      The OnApplyWindowInsetsListener on the root view was getting called twice, once with the correct insets WindowInsets{systemWindowInsets=Rect(0, 98 - 0, 168) and again with 0 insets WindowInsets{systemWindowInsets=Rect(0, 0 - 0, 0). So I'm only setting margins on the non-zero insets.



                      In the layout:



                      <androidx.constraintlayout.widget.ConstraintLayout
                      android:layout_width="match_parent"
                      android:layout_height="match_parent"
                      android:id="@+id/root_view">

                      <FrameLayout
                      android:layout_width="0dp"
                      android:layout_height="0dp"
                      android:id="@+id/root_content"
                      app:layout_constraintTop_toTopOf="parent"
                      app:layout_constraintBottom_toBottomOf="parent"
                      app:layout_constraintLeft_toLeftOf="parent"
                      app:layout_constraintRight_toRightOf="parent"/>

                      <LinearLayout
                      android:layout_width="match_parent"
                      android:layout_height="wrap_content"
                      android:id="@+id/toolbar_layout"
                      app:layout_constraintTop_toTopOf="parent">

                      <androidx.appcompat.widget.Toolbar
                      android:layout_width="match_parent"
                      android:layout_height="?attr/actionBarSize"
                      android:id="@+id/toolbar">

                      <TextView
                      android:layout_width="wrap_content"
                      android:layout_height="wrap_content"
                      android:id="@+id/toolbar_title"
                      android:textStyle="bold"
                      android:layout_gravity="center" />

                      </androidx.appcompat.widget.Toolbar>
                      </LinearLayout>
                      </androidx.constraintlayout.widget.ConstraintLayout>





                      share|improve this answer






























                        0














                        Here's what I had to do to get both completely transparent status bar and navigation bar, with insets applied:



                        My root view is a ContstraintLayout. Somehow it's working even without fitsSystemWindows and I'm getting the insets for both the top and bottom, which I've applied to my Toolbar and FrameLayout margins.



                        In the theme:



                        <item name="android:statusBarColor">@android:color/transparent</item>
                        <item name="android:navigationBarColor">@android:color/transparent</item>
                        <item name="android:windowTranslucentNavigation">false</item>
                        <item name="android:windowTranslucentStatus">true</item>
                        <item name="android:windowDrawsSystemBarBackgrounds">true</item>



                        setImmersive function in Activity:



                        I've created this function to apply the insets and window flags required to achieve the immersive look for a layout which can have:




                        • Root view


                          • Top view

                          • Content

                          • Bottom view




                            /**
                        * Apply immersive mode to this activity
                        * @param rootView the root layout which will receive the window insets
                        * @param topView the top view to apply insets to (optional)
                        * @param bottomView the bottom view to apply insets to (optional)
                        */
                        fun setImmersive(rootView: ViewGroup, topView: View? = null, bottomView: View? = null) {

                        window.addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS)

                        rootView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                        bottomView?.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION

                        rootView.setOnApplyWindowInsetsListener { _, insets ->
                        Log.d(javaClass.simpleName + " windowInsets", insets.toString())

                        // Apply the top insets
                        if (topView != null) {
                        insets.systemWindowInsetTop.apply {
                        if (this > 0) {
                        Log.d(javaClass.simpleName, "applying windowInsetTop $this")
                        val layoutParams = topView.layoutParams as ViewGroup.MarginLayoutParams
                        layoutParams.topMargin = this
                        topView.layoutParams = layoutParams
                        }
                        }
                        }

                        // Apply the bottom insets
                        if (bottomView != null) {
                        insets.systemWindowInsetBottom.apply {
                        if (this > 0) {
                        Log.d(javaClass.simpleName, "applying windowInsetBottom $this")
                        val layoutParams = bottomView.layoutParams as ViewGroup.MarginLayoutParams
                        layoutParams.bottomMargin = this
                        bottomView.layoutParams = layoutParams
                        }
                        }
                        }

                        insets.consumeSystemWindowInsets()
                        }
                        }


                        Call this function in your onCreate eg.:



                        override fun onCreate(savedInstanceState: Bundle?) {
                        super.onCreate(savedInstanceState)
                        setContentView(R.layout.brand_activity)
                        setImmersive(root_view, topView = toolbar, bottomView = root_content)
                        }


                        The OnApplyWindowInsetsListener on the root view was getting called twice, once with the correct insets WindowInsets{systemWindowInsets=Rect(0, 98 - 0, 168) and again with 0 insets WindowInsets{systemWindowInsets=Rect(0, 0 - 0, 0). So I'm only setting margins on the non-zero insets.



                        In the layout:



                        <androidx.constraintlayout.widget.ConstraintLayout
                        android:layout_width="match_parent"
                        android:layout_height="match_parent"
                        android:id="@+id/root_view">

                        <FrameLayout
                        android:layout_width="0dp"
                        android:layout_height="0dp"
                        android:id="@+id/root_content"
                        app:layout_constraintTop_toTopOf="parent"
                        app:layout_constraintBottom_toBottomOf="parent"
                        app:layout_constraintLeft_toLeftOf="parent"
                        app:layout_constraintRight_toRightOf="parent"/>

                        <LinearLayout
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:id="@+id/toolbar_layout"
                        app:layout_constraintTop_toTopOf="parent">

                        <androidx.appcompat.widget.Toolbar
                        android:layout_width="match_parent"
                        android:layout_height="?attr/actionBarSize"
                        android:id="@+id/toolbar">

                        <TextView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:id="@+id/toolbar_title"
                        android:textStyle="bold"
                        android:layout_gravity="center" />

                        </androidx.appcompat.widget.Toolbar>
                        </LinearLayout>
                        </androidx.constraintlayout.widget.ConstraintLayout>





                        share|improve this answer




























                          0












                          0








                          0







                          Here's what I had to do to get both completely transparent status bar and navigation bar, with insets applied:



                          My root view is a ContstraintLayout. Somehow it's working even without fitsSystemWindows and I'm getting the insets for both the top and bottom, which I've applied to my Toolbar and FrameLayout margins.



                          In the theme:



                          <item name="android:statusBarColor">@android:color/transparent</item>
                          <item name="android:navigationBarColor">@android:color/transparent</item>
                          <item name="android:windowTranslucentNavigation">false</item>
                          <item name="android:windowTranslucentStatus">true</item>
                          <item name="android:windowDrawsSystemBarBackgrounds">true</item>



                          setImmersive function in Activity:



                          I've created this function to apply the insets and window flags required to achieve the immersive look for a layout which can have:




                          • Root view


                            • Top view

                            • Content

                            • Bottom view




                              /**
                          * Apply immersive mode to this activity
                          * @param rootView the root layout which will receive the window insets
                          * @param topView the top view to apply insets to (optional)
                          * @param bottomView the bottom view to apply insets to (optional)
                          */
                          fun setImmersive(rootView: ViewGroup, topView: View? = null, bottomView: View? = null) {

                          window.addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS)

                          rootView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                          bottomView?.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION

                          rootView.setOnApplyWindowInsetsListener { _, insets ->
                          Log.d(javaClass.simpleName + " windowInsets", insets.toString())

                          // Apply the top insets
                          if (topView != null) {
                          insets.systemWindowInsetTop.apply {
                          if (this > 0) {
                          Log.d(javaClass.simpleName, "applying windowInsetTop $this")
                          val layoutParams = topView.layoutParams as ViewGroup.MarginLayoutParams
                          layoutParams.topMargin = this
                          topView.layoutParams = layoutParams
                          }
                          }
                          }

                          // Apply the bottom insets
                          if (bottomView != null) {
                          insets.systemWindowInsetBottom.apply {
                          if (this > 0) {
                          Log.d(javaClass.simpleName, "applying windowInsetBottom $this")
                          val layoutParams = bottomView.layoutParams as ViewGroup.MarginLayoutParams
                          layoutParams.bottomMargin = this
                          bottomView.layoutParams = layoutParams
                          }
                          }
                          }

                          insets.consumeSystemWindowInsets()
                          }
                          }


                          Call this function in your onCreate eg.:



                          override fun onCreate(savedInstanceState: Bundle?) {
                          super.onCreate(savedInstanceState)
                          setContentView(R.layout.brand_activity)
                          setImmersive(root_view, topView = toolbar, bottomView = root_content)
                          }


                          The OnApplyWindowInsetsListener on the root view was getting called twice, once with the correct insets WindowInsets{systemWindowInsets=Rect(0, 98 - 0, 168) and again with 0 insets WindowInsets{systemWindowInsets=Rect(0, 0 - 0, 0). So I'm only setting margins on the non-zero insets.



                          In the layout:



                          <androidx.constraintlayout.widget.ConstraintLayout
                          android:layout_width="match_parent"
                          android:layout_height="match_parent"
                          android:id="@+id/root_view">

                          <FrameLayout
                          android:layout_width="0dp"
                          android:layout_height="0dp"
                          android:id="@+id/root_content"
                          app:layout_constraintTop_toTopOf="parent"
                          app:layout_constraintBottom_toBottomOf="parent"
                          app:layout_constraintLeft_toLeftOf="parent"
                          app:layout_constraintRight_toRightOf="parent"/>

                          <LinearLayout
                          android:layout_width="match_parent"
                          android:layout_height="wrap_content"
                          android:id="@+id/toolbar_layout"
                          app:layout_constraintTop_toTopOf="parent">

                          <androidx.appcompat.widget.Toolbar
                          android:layout_width="match_parent"
                          android:layout_height="?attr/actionBarSize"
                          android:id="@+id/toolbar">

                          <TextView
                          android:layout_width="wrap_content"
                          android:layout_height="wrap_content"
                          android:id="@+id/toolbar_title"
                          android:textStyle="bold"
                          android:layout_gravity="center" />

                          </androidx.appcompat.widget.Toolbar>
                          </LinearLayout>
                          </androidx.constraintlayout.widget.ConstraintLayout>





                          share|improve this answer















                          Here's what I had to do to get both completely transparent status bar and navigation bar, with insets applied:



                          My root view is a ContstraintLayout. Somehow it's working even without fitsSystemWindows and I'm getting the insets for both the top and bottom, which I've applied to my Toolbar and FrameLayout margins.



                          In the theme:



                          <item name="android:statusBarColor">@android:color/transparent</item>
                          <item name="android:navigationBarColor">@android:color/transparent</item>
                          <item name="android:windowTranslucentNavigation">false</item>
                          <item name="android:windowTranslucentStatus">true</item>
                          <item name="android:windowDrawsSystemBarBackgrounds">true</item>



                          setImmersive function in Activity:



                          I've created this function to apply the insets and window flags required to achieve the immersive look for a layout which can have:




                          • Root view


                            • Top view

                            • Content

                            • Bottom view




                              /**
                          * Apply immersive mode to this activity
                          * @param rootView the root layout which will receive the window insets
                          * @param topView the top view to apply insets to (optional)
                          * @param bottomView the bottom view to apply insets to (optional)
                          */
                          fun setImmersive(rootView: ViewGroup, topView: View? = null, bottomView: View? = null) {

                          window.addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS)

                          rootView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                          bottomView?.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION

                          rootView.setOnApplyWindowInsetsListener { _, insets ->
                          Log.d(javaClass.simpleName + " windowInsets", insets.toString())

                          // Apply the top insets
                          if (topView != null) {
                          insets.systemWindowInsetTop.apply {
                          if (this > 0) {
                          Log.d(javaClass.simpleName, "applying windowInsetTop $this")
                          val layoutParams = topView.layoutParams as ViewGroup.MarginLayoutParams
                          layoutParams.topMargin = this
                          topView.layoutParams = layoutParams
                          }
                          }
                          }

                          // Apply the bottom insets
                          if (bottomView != null) {
                          insets.systemWindowInsetBottom.apply {
                          if (this > 0) {
                          Log.d(javaClass.simpleName, "applying windowInsetBottom $this")
                          val layoutParams = bottomView.layoutParams as ViewGroup.MarginLayoutParams
                          layoutParams.bottomMargin = this
                          bottomView.layoutParams = layoutParams
                          }
                          }
                          }

                          insets.consumeSystemWindowInsets()
                          }
                          }


                          Call this function in your onCreate eg.:



                          override fun onCreate(savedInstanceState: Bundle?) {
                          super.onCreate(savedInstanceState)
                          setContentView(R.layout.brand_activity)
                          setImmersive(root_view, topView = toolbar, bottomView = root_content)
                          }


                          The OnApplyWindowInsetsListener on the root view was getting called twice, once with the correct insets WindowInsets{systemWindowInsets=Rect(0, 98 - 0, 168) and again with 0 insets WindowInsets{systemWindowInsets=Rect(0, 0 - 0, 0). So I'm only setting margins on the non-zero insets.



                          In the layout:



                          <androidx.constraintlayout.widget.ConstraintLayout
                          android:layout_width="match_parent"
                          android:layout_height="match_parent"
                          android:id="@+id/root_view">

                          <FrameLayout
                          android:layout_width="0dp"
                          android:layout_height="0dp"
                          android:id="@+id/root_content"
                          app:layout_constraintTop_toTopOf="parent"
                          app:layout_constraintBottom_toBottomOf="parent"
                          app:layout_constraintLeft_toLeftOf="parent"
                          app:layout_constraintRight_toRightOf="parent"/>

                          <LinearLayout
                          android:layout_width="match_parent"
                          android:layout_height="wrap_content"
                          android:id="@+id/toolbar_layout"
                          app:layout_constraintTop_toTopOf="parent">

                          <androidx.appcompat.widget.Toolbar
                          android:layout_width="match_parent"
                          android:layout_height="?attr/actionBarSize"
                          android:id="@+id/toolbar">

                          <TextView
                          android:layout_width="wrap_content"
                          android:layout_height="wrap_content"
                          android:id="@+id/toolbar_title"
                          android:textStyle="bold"
                          android:layout_gravity="center" />

                          </androidx.appcompat.widget.Toolbar>
                          </LinearLayout>
                          </androidx.constraintlayout.widget.ConstraintLayout>






                          share|improve this answer














                          share|improve this answer



                          share|improve this answer








                          edited Feb 27 at 19:57

























                          answered Feb 23 at 13:27









                          basharovVbasharovV

                          12




                          12






























                              draft saved

                              draft discarded




















































                              Thanks for contributing an answer to Stack Overflow!


                              • Please be sure to answer the question. Provide details and share your research!

                              But avoid



                              • Asking for help, clarification, or responding to other answers.

                              • Making statements based on opinion; back them up with references or personal experience.


                              To learn more, see our tips on writing great answers.




                              draft saved


                              draft discarded














                              StackExchange.ready(
                              function () {
                              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53469643%2fonapplywindowinsetslistener-gives-systemwindowinsetbottom-that-is-always-0%23new-answer', 'question_page');
                              }
                              );

                              Post as a guest















                              Required, but never shown





















































                              Required, but never shown














                              Required, but never shown












                              Required, but never shown







                              Required, but never shown

































                              Required, but never shown














                              Required, but never shown












                              Required, but never shown







                              Required, but never shown







                              Popular posts from this blog

                              Create new schema in PostgreSQL using DBeaver

                              Deepest pit of an array with Javascript: test on Codility

                              Fotorealismo