【问题标题】:Reverting Window Insets on fragment change在片段更改时恢复窗口插图
【发布时间】:2021-12-23 15:19:24
【问题描述】:

我有三个片段。我想在一个片段上应用透明状态栏。为此,我在底部导航栏的setOnItemSelectedListener 方法上调用了以下隐藏方法。还添加了我现在得到的图像

private fun hideStatusBar() {
    window.statusBarColor = ContextCompat.getColor(this@SuperActivity, R.color.transparent)
    WindowCompat.setDecorFitsSystemWindows(window, false)
    ViewCompat.setOnApplyWindowInsetsListener(binding.root) { view, windowInsets ->
      val insets = windowInsets.getInsets(WindowInsetsCompat.Type.navigationBars())

      view.updateLayoutParams<ViewGroup.MarginLayoutParams> {
        leftMargin = insets.left
        rightMargin = insets.right
        bottomMargin = insets.bottom
      }
      WindowInsetsCompat.CONSUMED
    }
  }
    

  private fun showStatusBar() {
    window.statusBarColor = ContextCompat.getColor(this@SuperActivity, R.color.transparent)
    WindowCompat.setDecorFitsSystemWindows(window, true)
  }

我在片段调用隐藏方法时得到了适当的行为。

但是当我点击另一个片段(需要显示状态栏的片段)时,我得到以下行为:

【问题讨论】:

  • 您是否将这个WindowCompat.setDecorFitsSystemWindows(window, false) 还原为其他片段?
  • 是的。正如您在 showStatusBar() 方法中看到的那样。我使用 WindowCompat.setDecorFitsSystemWindows(window, true) 恢复了这个

标签: android android-fragments android-bottomnavigationview windowinsets


【解决方案1】:

下边距默认为0(或根布局“binding.root”中的指定值)

所以,你需要重新设置下边距;如果它已经是0;那么你可以:

private fun showStatusBar() {
    window.statusBarColor = ContextCompat.getColor(this@SuperActivity, R.color.transparent)
    WindowCompat.setDecorFitsSystemWindows(window, true)

    ViewCompat.setOnApplyWindowInsetsListener(binding.root) { view, windowInsets ->
      val insets = windowInsets.getInsets(WindowInsetsCompat.Type.navigationBars())

      view.updateLayoutParams<ViewGroup.MarginLayoutParams> {
        bottomMargin = 0 // reset the margin
      }
      WindowInsetsCompat.CONSUMED
    }
  }
}

或者如果它是别的东西;那么您需要将其从 dp 转换为像素并将其设置为 bottomMargin

如果您在 binding.root 中有一些指定的边距值,则同样适用;但我认为你没有,因为问题只出现在底部。

更新:

setOnApplyWindowInsetsListener 方法不会在 showStatusBar 方法中调用。因为在这种情况下,Window Insets 没有改变。由于我们在 hideStatusBar 方法中添加了边距,所以您在导航栏下方看到的这个空间来自 hideStatusBar 方法。

虽然应该触发监听,但是可以直接更新root:

binding.root.updateLayoutParams<ViewGroup.MarginLayoutParams> {
    bottomMargin = 0
}

但请注意,setDecorFitsSystemWindows 可能需要一些时间才能更新,因此updateLayoutParams 不会产生效果,因此,您可能需要稍作延迟:

Handler(Looper.getMainLooper()).postDelayed( {
    binding.root.updateLayoutParams<ViewGroup.MarginLayoutParams> {
        bottomMargin = 0
    }
 }, 0.1.toLong())

【讨论】:

  • 但是最好有一个ViewCompat.setOnApplyWindowInsetsListener 来处理这两种情况;你可以做一个简单的条件
  • 不。在 showStatusBar 方法中不调用 setOnApplyWindowInsetsListener 方法。因为在这种情况下,Window Insets 没有改变。因为,我们在 hideStatusBar 方法中添加了边距,所以您在导航栏下方看到的这个空间来自 hideStatusBar 方法。这就是为什么我要将窗口插图还原为初始插图的原因
  • 是的。谢谢@Zain。这就是修复。您能否也更新答案中的最后一条评论。这样我就可以批准它
  • 欢迎@TahaAsif.. 但请注意,这可能因设备而异。根据我的测试,直接调用没有效果;我不得不对此稍作延迟;我也更新了答案
  • 非常感谢@Zain。祝好运。批准您的回答。
猜你喜欢
  • 2013-08-27
  • 2017-08-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多