在片段更改时恢复窗口插图

Posted

技术标签:

【中文标题】在片段更改时恢复窗口插图【英文标题】: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) 恢复了这个 【参考方案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。祝好运。批准您的回答。

以上是关于在片段更改时恢复窗口插图的主要内容,如果未能解决你的问题,请参考以下文章

在片段中实现对话框时,必须在添加内容之前请求窗口功能

JavaFX 8:舞台插图(窗户装饰厚度)?

父级恢复时 Qt::Tool 出现太快

无法使用带有 Visual Studio 2010 的 Windows 窗体恢复设计器视图窗口

QT 布局管理器在移动窗口之前隐藏小部件时不会恢复空间

C++ 使用 ShowWindow 恢复窗口会禁用其最小化功能