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

时间:2015-05-31 07:13:02

标签: android navigation-drawer android-design-library androiddesignsupport

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

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

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

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

结果如下:

此:

After scroll

卡住了:

Then change

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

修改 可能存在错误,只有在重新启动应用程序时才会调用AppBarLayout偏移更改侦听器(按下后退按钮并打开应用程序),并在激烈搜索后再次停止调用。

8 个答案:

答案 0 :(得分:46)

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

答案 1 :(得分:32)

首先在MainActivity中获取AppBarLayout引用,然后在要替换的片段的暂停状态下,使用下面的方法展开工具栏:

MainActivity.appbar.setExpanded(true,true);

或关闭工具栏:

MainActivity.appbar.setExpanded(false,true);

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

答案 2 :(得分:12)

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

appBarLayout.setExpanded(true/false);
  

public void setExpanded(boolean expanded

     

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

     

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

     

展开如果布局应该完全展开,则为true;如果布局应完全展开,则为false

答案 3 :(得分:3)

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

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

答案 4 :(得分:2)

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

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

答案 5 :(得分:0)

正如document所说

  

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

     
      
  • 展开布尔值:如果布局应完全展开,则为true;如果布局应完全展开,则为false
  •   
  • animate 布尔值:是否为新状态设置动画
  •   

所以首先你需要

AppBarLayout 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 

答案 6 :(得分:0)

public void insert (String strIn, int intIn)
    {
    String lowerIn = strIn.toLowerCase();

    Node temp = listName;
    Node add = new Node (strIn, intIn);
    Node pointer = listName;

    if (pointer != null)//&& strIn.compareTo (lowerTemp) <= 0)
    {
        if (strIn.compareTo (pointer.strName.toLowerCase()) == 0)
        {
        add.nextName = listName;
        listName = add;
        }

        else if (strIn.compareTo (pointer.strName.toLowerCase()) < 0)
        {
        while (pointer.nextName != null && strIn.compareTo (pointer.nextName.strName.toLowerCase()) < 0)
        {
            pointer = pointer.nextName;
        }

        add.nextName = pointer.nextName;
        pointer.nextName = add;
        }

        else if (strIn.compareTo (pointer.strName.toLowerCase()) > 0)
        {
        while (pointer.nextName != null && strIn.compareTo (pointer.nextName.strName.toLowerCase()) > 0)
        {
            pointer = pointer.nextName;
        }

        add.nextName = pointer.nextName;
        pointer.nextName = add;
        }
    }

    else
    {
        listName = add;
    }

    pointer = new Node ();
    pointer = listNumber;
    temp = listNumber;

    //System.out.println ("pointer beginning" + pointer.intNumber);

    if (pointer != null)
    {
        if (intIn <= pointer.intNumber)
        {
        add.nextNumber = pointer;
        listNumber = add;
        }

        else
        {
        while (pointer.nextNumber != null && pointer.nextNumber.intNumber < intIn)
        {
            temp = pointer;
            pointer = pointer.nextNumber;
        }

        if (pointer.nextNumber != null && pointer.intNumber <= intIn && intIn <= pointer.nextNumber.intNumber)
        {
            add.nextNumber = pointer.nextNumber;
            pointer.nextNumber = add;
        }

        else if (pointer.nextNumber == null)
        {
            if (pointer.intNumber <= intIn)
            {
            pointer.nextNumber = add;
            }

            else
            {
            add.nextNumber = pointer;
            temp.nextNumber = add;
            }
        }
        }
    }

    else
    {
        listNumber = add;
    }
    }

答案 7 :(得分:0)

我遇到了类似的问题。当我动态调整它的大小时,我的布局被放置得比需要的高(像这里)或更低。它是在 FrameLayout 中以编程方式替换的 Fragment。 我做了什么:我开始在改变 FrameLayout 大小时重新创建我的 Fragment。

myFragment = new MyFragment();
getSupportFragmentManager().beginTransaction()
                .replace(R.id.frame_layout, myFragment)
                .commit();