通过 FragmentTransaction 添加的片段的 fitsSystemWindows 效果消失了 [英] fitsSystemWindows effect gone for fragments added via FragmentTransaction

查看:15
本文介绍了通过 FragmentTransaction 添加的片段的 fitsSystemWindows 效果消失了的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个带有导航抽屉和全出血片段的活动(顶部的图像必须出现在棒棒糖的半透明系统栏后面).虽然我有一个临时解决方案,通过在 Activity 的 XML 中简单地使用 标签来膨胀 Fragment,但它看起来不错.

I have an Activity with navigation drawer and full-bleed Fragment (with image in the top that must appear behind translucent system bar on Lollipop). While I had an interim solution where the Fragment was inflated by simply having <fragment> tag in Activity's XML, it looked fine.

然后我不得不将 替换为 并执行片段事务,现在片段不再出现在系统栏后面,尽管fitsSystemWindows 在所有必需的层次结构中设置为 true.

Then I had to replace <fragment> with <FrameLayout> and perform fragment transactions, and now the fragment does not appear behind the system bar anymore, despite fitsSystemWindows is set to true across all required hierarchy.

我相信 <fragment> 在 Activity 的布局中膨胀的方式与单独膨胀的方式之间可能存在一些差异.我在谷歌上搜索并找到了一些 KitKat 的解决方案,但这些都不适合我(棒棒糖).

I believe there might be some difference between how <fragment> gets inflated within Activity's layout vs on its own. I googled and found some solutions for KitKat, but neither of those worked for me (Lollipop).

activity.xml

<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
                                        xmlns:app="http://schemas.android.com/apk/res-auto"
                                        android:id="@+id/drawer_layout"
                                        android:layout_height="match_parent"
                                        android:layout_width="match_parent"
                                        android:fitsSystemWindows="true">

    <FrameLayout
            android:id="@+id/fragment_host"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fitsSystemWindows="true">

    </FrameLayout>

    <android.support.design.widget.NavigationView
            android:id="@+id/nav_view"
            android:layout_height="match_parent"
            android:layout_width="wrap_content"
            android:layout_gravity="start"
            android:fitsSystemWindows="true"/>

</android.support.v4.widget.DrawerLayout>

fragment.xml

<android.support.design.widget.CoordinatorLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fitsSystemWindows="true">

    <android.support.design.widget.AppBarLayout
            android:layout_width="match_parent"
            android:layout_height="224dp"
            android:fitsSystemWindows="true"
            android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
...

它在 activity.xml 是这样的情况下工作:

It worked when activity.xml was this way:

<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
                                        xmlns:app="http://schemas.android.com/apk/res-auto"
                                        android:id="@+id/drawer_layout"
                                        android:layout_height="match_parent"
                                        android:layout_width="match_parent"
                                        android:fitsSystemWindows="true">

    <fragment xmlns:android="http://schemas.android.com/apk/res/android"
              xmlns:tools="http://schemas.android.com/tools"
              android:id="@+id/fragment"
              android:name="com.actinarium.random.ui.home.HomeCardsFragment"
              tools:layout="@layout/fragment_home"
              android:layout_width="match_parent"
              android:layout_height="match_parent"/>

    <android.support.design.widget.NavigationView
            android:id="@+id/nav_view"
            android:layout_height="match_parent"
            android:layout_width="wrap_content"
            android:layout_gravity="start"
            android:fitsSystemWindows="true"/>

</android.support.v4.widget.DrawerLayout>

推荐答案

当你使用时,你的Fragment的onCreateView中返回的布局是直接附加的代替 标记(如果您查看视图层次结构,您将永远不会真正看到 标记.

When you use <fragment>, the layout returned in your Fragment's onCreateView is directly attached in place of the <fragment> tag (you'll never actually see a <fragment> tag if you look at your View hierarchy.

因此在 的情况下,你有

Therefore in the <fragment> case, you have

DrawerLayout
  CoordinatorLayout
    AppBarLayout
    ...
  NavigationView

类似于 cheesesquare 的工作方式.这是有效的,因为如这篇博文所述,DrawerLayoutCoordinatorLayoutfitsSystemWindows 如何应用于它们都有不同的规则——它们都用它来插入他们的子视图,但 对每个孩子调用 dispatchApplyWindowInsets(),允许他们访问 fitsSystemWindows="true" 属性.

Similar to how cheesesquare works. This works because, as explained in this blog post, DrawerLayout and CoordinatorLayout both have different rules on how fitsSystemWindows applies to them - they both use it to inset their child Views, but also call dispatchApplyWindowInsets() on each child, allowing them access to the fitsSystemWindows="true" property.

这与 FrameLayout 等布局的默认行为不同,当您使用 fitsSystemWindows="true" 时,它会消耗所有插入,盲目地应用填充而不通知任何子视图(这是博客文章的深度优先"部分).

This is a difference from the default behavior with layouts such as FrameLayout where when you use fitsSystemWindows="true" is consumes all insets, blindly applying padding without informing any child views (that's the 'depth first' part of the blog post).

因此,当您将 标记替换为 FrameLayout 和 FragmentTransactions 时,您的视图层次结构变为:

So when you replace the <fragment> tag with a FrameLayout and FragmentTransactions, your view hierarchy becomes:

DrawerLayout
  FrameLayout
    CoordinatorLayout
      AppBarLayout
      ...
  NavigationView

当 Fragment 的视图被插入到 FrameLayout 中时.该视图对将 fitsSystemWindows 传递给子视图一无所知,因此您的 CoordinatorLayout 永远不会看到该标志或执行其自定义行为.

as the Fragment's view is inserted into the FrameLayout. That View doesn't know anything about passing fitsSystemWindows to child views, so your CoordinatorLayout never gets to see that flag or do its custom behavior.

解决问题实际上相当简单:用另一个CoordinatorLayout替换您的FrameLayout.这确保 fitsSystemWindows="true" 从 Fragment 传递到新膨胀的 CoordinatorLayout.

Fixing the problem is actually fairly simple: replace your FrameLayout with another CoordinatorLayout. This ensures the fitsSystemWindows="true" gets passed onto the newly inflated CoordinatorLayout from the Fragment.

替代且同样有效的解决方案是创建 FrameLayout 的自定义子类并覆盖 onApplyWindowInsets() 分派给每个孩子(在您的情况下只是一个)或使用 ViewCompat.setOnApplyWindowInsetsListener()方法来拦截调用代码并从那里分派(不需要子类).更少的代码通常是最容易维护的,所以我不一定建议通过 CoordinatorLayout 解决方案来执行这些路线,除非您对此有强烈的感觉.

Alternate and equally valid solutions would be to make a custom subclass of FrameLayout and override onApplyWindowInsets() to dispatch to each child (in your case just the one) or use the ViewCompat.setOnApplyWindowInsetsListener() method to intercept the call in code and dispatch from there (no subclass required). Less code is usually the easiest to maintain, so I wouldn't necessarily recommend going these routes over the CoordinatorLayout solution unless you feel strongly about it.

这篇关于通过 FragmentTransaction 添加的片段的 fitsSystemWindows 效果消失了的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆