如何实现向上滚动时显示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
- 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" />
- 代码动态设置:
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
相关产品推荐
相关产品推荐

