You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现向上滚动时显示FAB、向下滚动时隐藏FAB?当前实现异常

解决FAB随滚动方向即时显示/隐藏的问题

看来你现在的FAB行为只在滚动到顶部/底部时触发,而不是滚动方向一变就立刻响应对吧?这是因为当前实现只判断了滚动边界,没监听滚动方向的变化。下面给你完整的解决方案:

核心思路

我们要自定义一个CoordinatorLayout.Behavior,通过记录上一次的滚动位置,对比当前滚动偏移量判断方向:

  • 用户向下滚动(内容向上移动,dy > 0):立即隐藏FAB
  • 用户向上滚动(内容向下移动,dy < 0):立即显示FAB

完整代码实现

public class ScrollAwareFABBehavior extends FloatingActionButton.Behavior {
    private int lastScrollY = 0;

    public ScrollAwareFABBehavior(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public boolean onStartNestedScroll(@NonNull CoordinatorLayout coordinatorLayout, 
                                       @NonNull FloatingActionButton child, 
                                       @NonNull View directTargetChild, 
                                       @NonNull View target, 
                                       int axes, 
                                       int type) {
        // 只响应垂直滚动事件
        return axes == ViewCompat.SCROLL_AXIS_VERTICAL;
    }

    @Override
    public void onNestedScroll(@NonNull CoordinatorLayout coordinatorLayout, 
                               @NonNull FloatingActionButton child, 
                               @NonNull View target, 
                               int dxConsumed, 
                               int dyConsumed, 
                               int dxUnconsumed, 
                               int dyUnconsumed, 
                               int type, 
                               @NonNull int[] consumed) {
        super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, type, consumed);
        
        // 根据dyConsumed判断滚动方向
        if (dyConsumed > 0 && lastScrollY <= target.getScrollY()) {
            // 向下滚动:隐藏FAB,带动画
            if (child.getVisibility() == View.VISIBLE) {
                ViewCompat.animate(child).scaleX(0f).scaleY(0f).setDuration(200).start();
                child.setVisibility(View.INVISIBLE);
            }
        } else if (dyConsumed < 0 && lastScrollY >= target.getScrollY()) {
            // 向上滚动:显示FAB,带动画
            if (child.getVisibility() != View.VISIBLE) {
                ViewCompat.animate(child).scaleX(1f).scaleY(1f).setDuration(200).start();
                child.setVisibility(View.VISIBLE);
            }
        }
        // 更新上一次滚动位置,避免重复触发动画
        lastScrollY = target.getScrollY();
    }
}

如何使用这个Behavior

  1. XML静态设置:给你的FAB添加layout_behavior属性:
<com.google.android.material.floatingactionbutton.FloatingActionButton
    android:id="@+id/fab"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:layout_behavior="com.yourpackage.ScrollAwareFABBehavior" />
  1. 代码动态设置:
FloatingActionButton fab = findViewById(R.id.fab);
CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) fab.getLayoutParams();
params.setBehavior(new ScrollAwareFABBehavior(this, null));
fab.setLayoutParams(params);

细节说明

  • 用缩放动画代替平移,视觉过渡更自然(你也可以换成translationY动画)
  • 加入lastScrollY判断是为了避免滚动过程中重复执行动画,减少性能消耗
  • 只在FAB状态变化时触发动画,避免无效操作

内容的提问来源于stack exchange,提问作者blackHawk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:57:55