Act*_*ine 52 android android-layout android-fragments
我有一个带有导航抽屉和全出血碎片的活动(顶部的图像必须出现在Lollipop上的半透明系统栏后面).虽然我有一个临时解决方案,其中片段通过简单地<fragment>在Activity的XML 中标记而膨胀,但它看起来很好.
然后,我不得不更换<fragment>与<FrameLayout>和执行片段交易,现在的片段不,出现在系统栏的后面了,尽管fitsSystemWindows被设置为true所有所需的层级.
我相信<fragment>在Activity的布局与其自身的夸大之间可能存在一些差异.我用Google搜索并为KitKat找到了一些解决方案,但这些解决方案都不适用于我(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>
Run Code Online (Sandbox Code Playgroud)
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">
...
Run Code Online (Sandbox Code Playgroud)
当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">
<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>
Run Code Online (Sandbox Code Playgroud)
ian*_*ake 80
当您使用<fragment>,布局在片段的恢复onCreateView直接连接代替的<fragment>标签(你永远不会真正看到一个<fragment>标签,如果你看一下你的视图层次.
因此,在这种<fragment>情况下,你有
DrawerLayout
CoordinatorLayout
AppBarLayout
...
NavigationView
Run Code Online (Sandbox Code Playgroud)
与cheesesquare的工作方式类似.这样做是因为,在解释这个博客帖子,DrawerLayout并CoordinatorLayout都对如何不同的规则fitsSystemWindows适用于他们-他们都用它来插页他们的孩子的意见,但也呼吁dispatchApplyWindowInsets()上的每个孩子,让他们获得了fitsSystemWindows="true"财产.
这与布局的默认行为有所不同,例如FrameLayout当你使用时fitsSystemWindows="true"消耗所有插图,盲目地应用填充而不通知任何子视图(这是博客文章的"深度优先"部分).
因此,当您<fragment>使用FrameLayout和FragmentTransactions 替换标记时,您的视图层次结构将变为:
DrawerLayout
FrameLayout
CoordinatorLayout
AppBarLayout
...
NavigationView
Run Code Online (Sandbox Code Playgroud)
当Fragment的视图插入到FrameLayout.该视图对传递fitsSystemWindows给子视图一无所知,因此您CoordinatorLayout永远不会看到该标志或执行其自定义行为.
解决问题实际上非常简单:用另一个替换你FrameLayoutCoordinatorLayout.这可以确保fitsSystemWindows="true"将传递到CoordinatorLayoutFragment中新填充的内容.
替代且同样有效的解决方案是创建自定义子类FrameLayout并覆盖onApplyWindowInsets()以分派给每个子节点(在您的情况下只是一个)或使用ViewCompat.setOnApplyWindowInsetsListener()方法拦截代码中的调用并从那里调度(不需要子类).更少的代码通常是最容易维护的,因此我不一定建议在CoordinatorLayout解决方案上使用这些路由,除非您对此有强烈的感觉.
Mar*_*ius 20
我的问题与你的问题类似:我有一个底栏导航,它正在替换内容片段.现在的一些片段要画在状态栏(有CoordinatorLayout,AppBarLayout),别人不(与ConstraintLayout,Toolbar).
ConstraintLayout
FrameLayout
[the ViewGroup of your choice]
BottomNavigationView
Run Code Online (Sandbox Code Playgroud)
ianhanniballake添加另一层的建议CoordinatorLayout 不是我想要的,所以我创建了一个FrameLayout处理插入的自定义(就像他建议的那样),过了一段时间我发现了这个解决方案真的没有多少代码:
activity_main.xml中
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.example.app.WindowInsetsFrameLayout
android:id="@+id/fragment_container"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="@+id/bottom_navigation"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<BottomNavigationView
android:id="@+id/bottom_navigation"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</android.support.constraint.ConstraintLayout>
Run Code Online (Sandbox Code Playgroud)
WindowInsetsFrameLayout.java
/**
* FrameLayout which takes care of applying the window insets to child views.
*/
public class WindowInsetsFrameLayout extends FrameLayout {
public WindowInsetsFrameLayout(Context context) {
this(context, null);
}
public WindowInsetsFrameLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public WindowInsetsFrameLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
// Look for replaced fragments and apply the insets again.
setOnHierarchyChangeListener(new OnHierarchyChangeListener() {
@Override
public void onChildViewAdded(View parent, View child) {
requestApplyInsets();
}
@Override
public void onChildViewRemoved(View parent, View child) {
}
});
}
}
Run Code Online (Sandbox Code Playgroud)