54

我正在开发的应用程序包含一个在 Activity 中实现的 Navigation Drawer。活动布局如下:

<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>

这是一种很常见的模式,唯一变化频繁的是容器布局中的 Fragment。

如果任何 Fragment 具有滚动元素,则在滚动时,CoordinatorLayout 将愉快地进行位置转换,包括 Toolbar/AppBarLayout。

这里真正的问题是,当 Fragment 被替换时,工具栏的位置保持不变,即,如果工具栏被隐藏,它将保持原样,这不是预期的。

结果是这样的:

这个:

滚动后

卡住:

然后改变

在这种情况下如何重置工具栏位置?

编辑: 可能存在错误,仅在重新启动应用程序(按返回按​​钮并打开应用程序)时调用 AppBarLayout 偏移更改侦听器,并在激烈的甩动后停止再次调用。

4

9 回答 9

48

要重置滚动状态,只需获取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);

如果您想通过动画顺利重置,可以尝试调用onNestedFling

behavior.onNestedFling(coordinator, appbar, null, 0, -1000, true);
于 2015-06-09T10:25:58.030 回答
39

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

MainActivity.appbar.setExpanded(true,true);

和或关闭工具栏:

MainActivity.appbar.setExpanded(false,true);

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

于 2015-10-23T11:59:23.160 回答
13

将您的支持库更新到 v23,然后您可以使用:

appBarLayout.setExpanded(true/false);

public void setExpanded(布尔扩展

设置此 AppBarLayout 是否展开,如果它已经布局则动画。

与 AppBarLayout 的滚动一样,此方法依赖此布局作为 CoordinatorLayout 的直接子级。

expand 如果布局应该完全展开 ,则为 true,如果应该完全折叠,则为 false

于 2015-12-03T14:57:10.023 回答
3

@razzledazzle AppBarLayout 将 onOffsetChangedListeners 存储为 WeakReferences,这意味着它们会在需要时进行垃圾收集,例如当您进行激烈的投掷时。在此处查看解决方案:

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

于 2015-06-10T14:26:24.973 回答
2

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

scrollingElement.startNestedScroll(ViewCompat.SCROLL_AXIS_VERTICAL);
scrollingElement.dispatchNestedPreScroll(0, -Integer.MAX_VALUE, null, null);
scrollingElement.stopNestedScroll();
于 2015-06-07T16:43:22.683 回答
2

正如文件所说

AppBarLayout 支持
void setExpanded (boolean expand, boolean animate);
设置此 AppBarLayout 是否展开。

  • expand 布尔值:如果布局应该完全展开 ,则为 true,如果应该完全折叠,则为 false
  • animate boolean: 是否动画到新的状态

所以首先,你需要

AppBarLayout appBarLayout = findViewById(R.id.appBarLayout);

然后展开布局

appBarLayout.setExpanded(true, true); // with animation
appBarLayout.setExpanded(true, false); // without animation  

折叠布局

appBarLayout.setExpanded(false, true); // with animation
appBarLayout.setExpanded(false, false); // without animation 
于 2018-02-14T17:20:36.143 回答
2

用a替换或包裹FrameLayout内部,它将自动完成这项工作,而无需任何其他黑客......所以它看起来像这样:android.support.design.widget.CoordinatorLayoutandroid.support.v4.widget.NestedScrollView

<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>
于 2017-05-08T15:08:11.647 回答
0

我有一个类似的问题。当我动态调整它的大小时,我的布局要么高于需要(如这里),要么低于需要。它是以编程方式在 FrameLayout 中替换的 Fragment。我做了什么:我开始在更改 FrameLayout 大小时重新创建我的 Fragment。

myFragment = new MyFragment();
getSupportFragmentManager().beginTransaction()
                .replace(R.id.frame_layout, myFragment)
                .commit();
于 2021-04-23T15:21:46.710 回答
0
// Get the reference for appbar from layout
AppBarLayout appbar = rootView.findViewById(R.id.appbar);
//boolean expanded, boolean animate
appbar.setExpanded(true, true);
于 2019-12-20T03:35:29.427 回答