以编程方式折叠或展开CollapsingToolbarLayout

185

简单的问题,但我找不到答案。如何通过编程方式折叠或展开CollapsingToolbarLayout?

折叠工具栏

↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

展开工具栏


1
我也在想同样的事情。当用户点击嵌入式布局(例如图像)时,将工具栏扩展到全屏也可能很有趣。 - Moritz
我对那些忽略了 CollapsingToolbarLayout 不能自行展开或折叠的答案感到有些迷茫,更糟糕的是,其他评论让它看起来像是与版本有关的问题。实际上,你需要处理的是它的父级,这很有趣,因为 CollapsingToolbarLayout 可以禁用自己的折叠/展开,但出于某种原因它不能触发它们。 - Delark
11个回答

380

2
好的,谢谢你的提示,但是支持库v23非常有bug,所以我现在无法测试它,因为我需要保持在22.2.1版本。 - Tomas
现在您拥有23.0.1版本,其中包含一些修复。 - Mario Velasco
6
在支持库版本23.1.1中是否可以定义自定义动画?setExpanded(boolean,true)具有非常缓慢的动画... - Nifhel
我遇到了一个问题,我的布局中有一个可折叠的工具栏和一个位于其下方的recyclerview。当从recyclerview中删除项目时,工具栏的行为不恰当,因此我会展开应用程序栏布局,这样它就可以正常工作了。最终,我使用了appBarLayout.setExpanded(true, true)来进行动画处理。 - Ray Hunter
这只是部分展开/折叠 AppBarLayout。还有一个嵌套的 CoordinatorLayout 需要处理。 - IgorGanapolsky

48

我正在使用这段代码来实现可折叠工具栏,但是还没有找到展开它的方法。

public void collapseToolbar(){
    CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) appbarLayout.getLayoutParams();
    behavior = (AppBarLayout.Behavior) params.getBehavior();
    if(behavior!=null) {
        behavior.onNestedFling(rootLayout, appbarLayout, null, 0, 10000, true);
    }
}

编辑1:使用负velocityY的相同函数但工具栏没有展开到100%,并且最后一个参数为false应该可以正常工作

public void expandToolbar(){
    CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) appbarLayout.getLayoutParams();
    behavior = (AppBarLayout.Behavior) params.getBehavior();
    if(behavior!=null) {
        behavior.onNestedFling(rootLayout, appbarLayout, null, 0, -10000, false);
    }
}

编辑2:这段代码对我起了作用

public void expandToolbar(){
    CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) appbarLayout.getLayoutParams();
    behavior = (AppBarLayout.Behavior) params.getBehavior();
    if(behavior!=null) {
        behavior.setTopAndBottomOffset(0);
        behavior.onNestedPreScroll(rootLayout, appbarLayout, null, 0, 1, new int[2]);
    }
}
  • setTopAndBottomOffset可以扩展工具栏
  • onNestedPreScroll可以显示扩展工具栏内的内容

我会尝试自己实现Behavior。


2
如果您将onNestedFling的最后一个参数设置为false,则“Edit 1”也可以正常工作。 - Ricky Lee
2
params.getBehavior() 返回 null。在 xml 中,layout_behaviour 标签设置在兄弟 NestedScrollView 上,而不是 AppBarLayout 上。你能帮我吗? - User31689
谢谢。如果最后一个参数为false,则编辑1将正常工作。 :) - Sirelon
@GobletSky 我遇到了同样的问题。我在我的碎片中有一个NestedScrollView,并尝试在设置碎片之前调用onNestedFling方法。设置完碎片后,我成功地调用了这个方法。 - usp
@usp 实际上,我的问题完全不同(有点新手错误)。请看这里:https://dev59.com/h4zda4cB1Zd3GeqPlmL-#31182999 - User31689
显示剩余3条评论

34

您可以使用自定义动画程序来定义它展开或折叠的程度。只需使用setTopAndBottomOffset(int)即可。

这是一个示例:

CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) appBar.getLayoutParams();
final AppBarLayout.Behavior behavior = (AppBarLayout.Behavior) params.getBehavior();
if (behavior != null) {
    ValueAnimator valueAnimator = ValueAnimator.ofInt();
    valueAnimator.setInterpolator(new DecelerateInterpolator());
    valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            behavior.setTopAndBottomOffset((Integer) animation.getAnimatedValue());
            appBar.requestLayout();
        }
    });
    valueAnimator.setIntValues(0, -900);
    valueAnimator.setDuration(400);
    valueAnimator.start();
}

3
这是唯一一个可以让你动画到自定义偏移量的答案。非常感谢! - Guilherme Torres Castro
3
appBar.setExpanded(false, true); 可以翻译为“将应用栏收起,并且带有动画效果”。其中,第一个参数false表示应用栏被收起,第二个参数true表示带有动画效果。 - Puni
2
如果你想要扩展/折叠到“自定义”偏移量(例如进行多级折叠),那么你需要这个。@Puni - Palatis
1
这是最好的解决方案,用来动画化AppBar的偏移,如果您不想编写自定义行为。对代码片段的一个更新是调用valueAnimator.setIntValues(),将behavior.topAndBottomOffset的起始值作为参数传入,而不是0,以从当前AppBar偏移开始动画化。 - reel
使用自定义变量(-900)来设置valueAnimator.setIntValues的值并不是最好的解决方案,更好的方法是使用-(appBar.getTotalScrollRange()) - Ali Rezaiyan

12

我写了一个小扩展来改进AppBarLayout,它可以带有或不带动画来实现CollapsibleToolbarLayout的展开和折叠。它看起来正常工作。

可以尝试一下。

只需要使用它代替你的AppBarLayout,并且你可以调用与展开或折叠CollapsingToolbarLayout相关的方法。

在我的项目中,它完全按照预期运行,但是你可能需要微调在performExpandingWithAnimation()(特别是在perform...方法中)的抛掷/滚动值来与你的CollapsibleToolbarLayout完美匹配。


@ssdeno 请阅读 Github Gist 的 Readme.md。自支持库 v23 起已被弃用。自支持库v23 (转到 AndroidX) 以来,AppBarLayout 中有了 setExpanded 方法。 - Bartek Lipinski

8

使用mAppBarLayout.setExpanded(true)展开工具栏,使用mAppBarLayout.setExpanded(false)折叠工具栏。

如果您想通过编程的方式更改CollapsingToolbarLayout的高度,则只需使用mAppBarLayout.setLayoutParams(params)

展开:

CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) mAppBarLayout.getLayoutParams();
params.height = 3*200; // HEIGHT

mAppBarLayout.setLayoutParams(params);
mAppBarLayout.setExpanded(true);

折叠:

CoordinatorLayout.LayoutParams params =(CoordinatorLayout.LayoutParams) mAppBarLayout.getLayoutParams();
params.height = 3*80; // HEIGHT

mAppBarLayout.setLayoutParams(params);
mAppBarLayout.setExpanded(false);

5

对于那些想要使用onNestedPreScroll并且像我一样遇到错误的人。 如果没有这行代码,我会在onCreate中得到NullPointerException。

    CoordinatorLayout coordinator =(CoordinatorLayout)findViewById(R.id.tab_maincontent);
    CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) appBarLayout.getLayoutParams();
    //below line
    params.setBehavior(new AppBarLayout.Behavior() {});

这个问题可能导致程序运行不正常。

但我可以在 onCreate 方法中通过其他方式解决这个问题。

        scrollToolbarOnDelay();

并且...

    public void scrollToolbarOnDelay() {
            final Handler handler = new Handler();
            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    AppBarLayout appBarLayout = (AppBarLayout) findViewById(R.id.tab_appbar);
                    CoordinatorLayout coordinator = (CoordinatorLayout) findViewById(R.id.tab_maincontent);
                    CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) appBarLayout.getLayoutParams();
                    AppBarLayout.Behavior behavior = (AppBarLayout.Behavior) params.getBehavior();
         if(behavior!=null)
                    behavior.onNestedPreScroll(coordinator, appBarLayout, null, 0, 100, new int[]{0, 0});
         else
            scrollToolbarOnDelay()
                }
            }, 100);


        }

5

请尝试以下方法...

展开

appBarLayout.setExpanded(true, true);

回顾

appBarLayout.setExpanded(false, true);

在所有可用的解决方案中,这个对我起作用了! - Pravin Yadav

3

通过编程实现展开/折叠AppBarLayout:

fun expandAppBarLayout(expand: Boolean, isAnimationEnabled: Boolean){
    appBarLayout.setExpanded(expand, isAnimationEnabled);
}

1
这可能有助于展开或折叠:
appBarLayout.setActivated(true);
appBarLayout.setExpanded(true, true);

0

我一直在使用这个

 private fun collapseAppbar() {
        scrollView.postDelayed(Runnable {
            scrollView?.smoothScrollTo(50, 50)
        }, 400)
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接