如何重置由CoordinatorLayout控制的工具栏位置?

我正在处理的应用程序包含一个在“活动”中实施的导航抽屉。 活动布局如下:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.v4.widget.DrawerLayout android:id="@+id/drawer_layout" android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.design.widget.CoordinatorLayout android:id="@+id/coordinator" android:layout_width="match_parent" android:layout_height="match_parent"> <FrameLayout android:id="@+id/container" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior"> <include android:id="@+id/appbar" layout="@layout/appbar" /> </android.support.design.widget.CoordinatorLayout> <android.support.design.widget.NavigationView android:id="@+id/navigation_drawer" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="start" app:headerLayout="@layout/header_drawer" app:menu="@menu/menu_nav"> </android.support.design.widget.NavigationView> </android.support.v4.widget.DrawerLayout> </FrameLayout> 

这是一个非常常见的模式,只有经常变化的东西是容器布局中的碎片。

如果任何一个片段有一个滚动元素,在滚动时,CoordinatorLayout将很乐意进行位置翻译,包括工具栏/ AppBarLayout。

这里真正的问题是,当碎片被replace时,工具栏的位置保持不变,即,如果工具栏被隐藏,则它将保持不被打算的状态。

结果是这样的:

这个:

滚动后

卡住:

然后改变

如何重置这个案例的工具栏位置?

编辑:一个错误是可能的,AppBarLayout偏移量更改监听器只有当重新启动应用程序(按回来button,打开应用程序)才会被调用,并停止在激烈的一扔之后再次调用。

要重置滚动状态,只需获取AppBarLayout.Behavior对象

 CoordinatorLayout coordinator = (CoordinatorLayout) findViewById(R.id.coordinator); AppBarLayout appbar = (AppBarLayout) findViewById(R.id.appbar); CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) appbar.getLayoutParams(); AppBarLayout.Behavior behavior = (AppBarLayout.Behavior) params.getBehavior(); 

并手动调用onNestedPreScroll方法:

 int[] consumed = new int[2]; behavior.onNestedPreScroll(coordinator, appbar, null, 0, -1000, consumed); 

如果你想用animation顺利重置,你可以尝试调用onNestedFling来代替:

 behavior.onNestedFling(coordinator, appbar, null, 0, -1000, true); 

首先在你的MainActivity中获得一个AppBarLayout引用,然后在被replace的片段的暂停状态下,使用下面的方法展开工具栏:

 MainActivity.appbar.setExpanded(true,true); 

或者closures工具栏:

 MainActivity.appbar.setExpanded(false,true); 

第二个参数用于平滑滚动工具栏。

更新你的支持库至v23,然后你可以使用:

 appBarLayout.setExpanded(true/false); 

public void setExpanded(boolean extends)

设置此AppBarLayout是否展开,如果已经布置,则进行animation处理。

与AppBarLayout的滚动一样,此方法依赖于此布局是CoordinatorLayout的直接子对象。

如果布局应该完全展开,则展开为真;如果展开应完全展开,则展开为假

@razzledazzle AppBarLayout将onOffsetChangedListeners存储为WeakReferences,这意味着它们在需要的时候被垃圾回收,例如当你做了一个强烈的投掷。 看到解决scheme

https://code.google.com/p/android/issues/detail?id=176328

我在碎片更改之前使用此代码。

 scrollingElement.startNestedScroll(ViewCompat.SCROLL_AXIS_VERTICAL); scrollingElement.dispatchNestedPreScroll(0, -Integer.MAX_VALUE, null, null); scrollingElement.stopNestedScroll(); 

android.support.design.widget.CoordinatorLayoutFrameLayoutreplace为android.support.design.widget.CoordinatorLayout ,并自动完成这个工作,而不需要任何其他的hack ….所以它看起来像这样:

 <android.support.design.widget.CoordinatorLayout android:id="@+id/coordinator" android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.v4.widget.NestedScrollView android:id="@+id/container" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior"> <include android:id="@+id/appbar" layout="@layout/appbar" /> </android.support.design.widget.CoordinatorLayout>