如何确定 CollapsingToolbar 已折叠?

Posted

技术标签:

【中文标题】如何确定 CollapsingToolbar 已折叠?【英文标题】:How can I determine that CollapsingToolbar is collapsed? 【发布时间】:2015-10-30 14:22:18 【问题描述】:

我需要知道材料设计库中的 CollapsingToolbar 何时折叠。

【问题讨论】:

【参考方案1】:

正如 Marko 所说,这可以使用您自己的 OnOffsetChangedListener 实现来实现。

AppBarLayout appBarLayout = (AppBarLayout) view.findViewById(R.id.app_bar_layout);
appBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() 
        @Override
        public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) 
            if (Math.abs(verticalOffset) == appBarLayout.getTotalScrollRange()) 
                // Collapsed
             else if (verticalOffset == 0) 
                // Expanded
             else 
                // Somewhere in between
            
        
    ););

【讨论】:

这个解决方案似乎是最流行的一个。但是,就我而言,问题在于每次折叠/展开时都会调用addOnOffsetChangedListener,除非您停止移动手指。是否可以仅在展开或关闭状态并且仅在其中一个状态执行某些代码之后才检测状态? 这个解决方案就像一个魅力......只有一件事 - 因为我在某些条件下禁用了可折叠工具栏的滚动标志,所以 getTotalScrollRange() 对我来说是 0,因此它总是显示我“折叠”状态。在这种情况下,交换“if”和“else if”效果最好。【参考方案2】:

更新:由于支持23.1.1+版本,问题不再存在,无需使用监听器和禁用滑动刷新布局,它会工作应该的 (link)。


在您的 AppBarLayout

上实现 AppBarLayout.OnOffsetChangedListener 侦听器
AppBarLayout appBarLayout = (AppBarLayout) view.findViewById(R.id.app_bar_layout);
appBarLayout.addOnOffsetChangedListener(this);

并检查偏移量是否为0,表示工具栏已完全展开。

@Override
public void onOffsetChanged(AppBarLayout appBarLayout, int offset)

    if (offset == 0)
    
        // Fully expanded
    
    else
    
        // Not fully expanded or collapsed
    

【讨论】:

@Atieh 进一步解释一下,当折叠工具栏完全展开时,偏移值等于零(offset == 0) 我将if条件改为verticalOffset < -710,问题就解决了。不优雅,但它有效 检测是否完全折叠检查 Math.abs(offset) == appBarLayout 正如@Atieh 所说,这不是正确的答案,Upvotes 具有误导性,也许用户应该先尝试然后投票! 这个我会重新测试,如果有错误更正。【参考方案3】:

看看这个github gist

public class MyAppBarLayout extends AppBarLayout
        implements AppBarLayout.OnOffsetChangedListener 

    private State state;
    private OnStateChangeListener onStateChangeListener;

    public MyAppBarLayout(Context context) 
        super(context);
    

    public MyAppBarLayout(Context context, AttributeSet attrs) 
        super(context, attrs);
    

    @Override
    protected void onAttachedToWindow() 
        super.onAttachedToWindow();
        if (!(getLayoutParams() instanceof CoordinatorLayout.LayoutParams)
                || !(getParent() instanceof CoordinatorLayout)) 
            throw new IllegalStateException(
                    "MyAppBarLayout must be a direct child of CoordinatorLayout.");
        
        addOnOffsetChangedListener(this);
    

    @Override
    public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) 
        if (verticalOffset == 0) 
            if (onStateChangeListener != null && state != State.EXPANDED) 
                onStateChangeListener.onStateChange(State.EXPANDED);
            
            state = State.EXPANDED;
         else if (Math.abs(verticalOffset) >= appBarLayout.getTotalScrollRange()) 
            if (onStateChangeListener != null && state != State.COLLAPSED) 
                onStateChangeListener.onStateChange(State.COLLAPSED);
            
            state = State.COLLAPSED;
         else 
            if (onStateChangeListener != null && state != State.IDLE) 
                onStateChangeListener.onStateChange(State.IDLE);
            
            state = State.IDLE;
        
    

    public void setOnStateChangeListener(OnStateChangeListener listener) 
        this.onStateChangeListener = listener;
    

    public interface OnStateChangeListener 
        void onStateChange(State toolbarChange);
    

    public enum State 
        COLLAPSED,
        EXPANDED,
        IDLE
    

【讨论】:

你说得对,我添加了与问题相关的代码。 这工作很优雅@EdyBolos 非常感谢分享。完美无瑕!【参考方案4】:
 appBarLayout.addOnOffsetChangedListener(AppBarLayout.OnOffsetChangedListener  appBarLayout, verticalOffset ->

        if (Math.abs(verticalOffset)  >= appBarLayout.totalScrollRange)  // collapse
         else if (verticalOffset == 0)  // fully expand

         else  // scolling

        
    )

appBarLayout.totalScrollRange 在某些情况下并不总是等于verticalOffset,最好检查verticalOffset 是否大于totoalScrollRange

【讨论】:

【参考方案5】:
appBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() 

        @Override
        public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset)
 

            if (Math.abs(verticalOffset)-appBarLayout.getTotalScrollRange() == 0)
            
                //  on Collapse
            
            else
            
               //  on expand
            
        
    );

【讨论】:

以上是关于如何确定 CollapsingToolbar 已折叠?的主要内容,如果未能解决你的问题,请参考以下文章

使用 CollapsingToolbar 滚动时如何更新工具栏

如何在CollapsingToolbar中使用Map的点击事件

CollapsingToolbar, Viewpager 有 recyclerview 和 NestedScrollview

如何用CollapsingToolbar替换CoordinatorLayout中的CardView?

Jetpack Compose 折叠工具栏

AppBarLayout 上的 EdgeEffect