关于解决自定义FloatingActionButton滑动行为(Behavior)只隐藏不出现的问题

本文介绍了一个自定义FloatingActionButton Behavior时遇到的问题:在Android SDK 25及以上版本中,FAB隐藏后无法重新显示。通过分析CoordinatorLayout源码,找到了问题原因并提供了解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近在使用FloatingActionButton的时候,自定义了其Behavior,然后发现在SDK在25及以上的时候,出现了只能隐藏不能重新出现的问题(24及以下没有出现此问题),Behavior代码如下:

public class MyFabBehavior extends FloatingActionButton.Behavior {

    // 必须重写两个参数的构造方法,否则会报错
    public MyFabBehavior (Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    // 返回true时表示传递滑动参数,同时执行后面的滑动监听,返回false的话后面的onNestedScroll等方法就不会调用了
    // super是直接返回的false

    @Override
    public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, FloatingActionButton child, View directTargetChild, View target, int nestedScrollAxes) {
        // 判断如果是垂直滚动则返回true
        return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL;
    }

    @Override
    public void onNestedScroll(CoordinatorLayout coordinatorLayout, FloatingActionButton child, View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) {
        // 可以直接删掉super 进去之后发现super里面啥也没做
        // super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed);
        System.out.println("dyConsumed: " + dyConsumed);

        // 如果向上滑动 则隐藏
        if (dyConsumed > 0 && child.getVisibility() == View.VISIBLE) {
            child.hide();
        } else if (dyConsumed < 0  && child.getVisibility() != View.VISIBLE) {
            // 向下则显示
            child.show();
        }
    }
}

 后来进入CoordinatorLayout里面看了下,在该类的onNestedScroll()方法中对比24版本和25版本的SDK,发现25多了一点代码

@Override
    public void onNestedScroll(View target, int dxConsumed, int dyConsumed,
            int dxUnconsumed, int dyUnconsumed) {
        final int childCount = getChildCount();
        boolean accepted = false;

        for (int i = 0; i < childCount; i++) {
            final View view = getChildAt(i);
            if (view.getVisibility() == GONE) { // 这个判断就是比24多出的
                // If the child is GONE, skip...
                continue;
            }

            final LayoutParams lp = (LayoutParams) view.getLayoutParams();
            if (!lp.isNestedScrollAccepted()) {
                continue;
            }

            final Behavior viewBehavior = lp.getBehavior();
            if (viewBehavior != null) {
                viewBehavior.onNestedScroll(this, view, target, dxConsumed, dyConsumed,
                        dxUnconsumed, dyUnconsumed); // Behavior对事件的响应
                accepted = true;
            }
        }

        if (accepted) {
            onChildViewsChanged(EVENT_NESTED_SCROLL);
        }
    } 

就是因为多了上面那一行判断,而我们在自定义中Behavior中hide()的时候,将FloatingActionButton隐藏了,导致代码执行到上述标红部分的时候,就直接跳出了for循环,那就没法回调onNestedScroll()方法了。

所以解决方案就是:

不要用hide()方法,也不要使用setVisibility(GONE),可以使用setVisibility(INVISIBLE),或者将其移除屏幕显示范围来达到隐藏的效果
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值