FloatingActionButton的Behavior里面onNestedScroll()只调了一次?

onNestedScroll 像这种一遍滚一遍调的函数,只调一次怎么可以完美地完成我的任务

今天,在重写 FloatingActionButton.Behavior 的时候,遇到了问题,记录一下

第一个问题,在完成了 behavior 代码之后

public class ScrollFABBehavior extends FloatingActionButton.Behavior {

    @Override
    public boolean onStartNestedScroll(@NonNull CoordinatorLayout coordinatorLayout,
                                       @NonNull FloatingActionButton child,
                                       @NonNull View directTargetChild,
                                       @NonNull View target, int axes, int type) {
        // Ensure we react to vertical scrolling
        return axes == ViewCompat.SCROLL_AXIS_VERTICAL
                || super.onStartNestedScroll(coordinatorLayout, child, directTargetChild, target, axes);

    }

    @Override
    public void onNestedScroll(@NonNull CoordinatorLayout coordinatorLayout,
                               @NonNull FloatingActionButton child,
                               @NonNull View target,
                               int dxConsumed,
                               int dyConsumed,
                               int dxUnconsumed,
                               int dyUnconsumed,
                               int type) {
        super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, type);
        if (dyConsumed > 0 && child.getVisibility() == View.VISIBLE) {
            child.hide();
        } else if (dyConsumed <= 0 && child.getVisibility() != View.VISIBLE) {
            child.show();
        }
    }

}

用在 FAB 上的时候 出现了 异常

Could not inflate Behavior subclass com.example.....ScrollFABBehavior

仔细一看,shit,忘记了 从 xml 加载对应的 构造函数

加上就解决了

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

接下来是第二个问题

FAB 的 hide() 没有问题,可以hide 完之后 不show 了。

跟踪一下发现,onNestedScroll() 只调用了一次

/**
         * Called when a nested scroll in progress has updated and the target has scrolled or
         * attempted to scroll.
         *
         * <p>Any Behavior associated with the direct child of the CoordinatorLayout may elect
         * to accept the nested scroll as part of {@link #onStartNestedScroll}. Each Behavior
         * that returned true will receive subsequent nested scroll events for that nested scroll.
         * </p>
         *
         * <p><code>onNestedScroll</code> is called each time the nested scroll is updated by the
         * nested scrolling child, with both consumed and unconsumed components of the scroll
         * supplied in pixels. <em>Each Behavior responding to the nested scroll will receive the
         * same values.</em>
         * </p>
         *
         * @param coordinatorLayout the CoordinatorLayout parent of the view this Behavior is
         *                          associated with
         * @param child the child view of the CoordinatorLayout this Behavior is associated with
         * @param target the descendant view of the CoordinatorLayout performing the nested scroll
         * @param dxConsumed horizontal pixels consumed by the target's own scrolling operation
         * @param dyConsumed vertical pixels consumed by the target's own scrolling operation
         * @param dxUnconsumed horizontal pixels not consumed by the target's own scrolling
         *                     operation, but requested by the user
         * @param dyUnconsumed vertical pixels not consumed by the target's own scrolling operation,
         *                     but requested by the user
         * @param type the type of input which cause this scroll event
         *
         * @see NestedScrollingParent2#onNestedScroll(View, int, int, int, int, int)
         */

这好像是在逗我?我也看不懂,大概意思就是 这个函数在 scroll 的时候就会更新

可是并没有

解决办法:

@Override
    public void onNestedScroll(@NonNull CoordinatorLayout coordinatorLayout,
                               @NonNull FloatingActionButton child,
                               @NonNull View target,
                               int dxConsumed,
                               int dyConsumed,
                               int dxUnconsumed,
                               int dyUnconsumed,
                               int type) {
        super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, type);
        if (dyConsumed > 0 && child.getVisibility() == View.VISIBLE) {
            child.hide(new FloatingActionButton.OnVisibilityChangedListener() {
                @Override
                public void onShown(FloatingActionButton fab) {
                    super.onShown(fab);
                }

                @Override
                public void onHidden(FloatingActionButton fab) {
                    super.onHidden(fab);
                    fab.setVisibility(View.INVISIBLE);
                }
            });
        } else if (dyConsumed <= 0 && child.getVisibility() != View.VISIBLE) {
            child.show();
        }
    }

跟上面的区别就是 hide 的时候 别把 FAB visibility 变成GONE,而是变成 INVISIBLE

GONE 与 INVISIBLE 的区别就不说了。

为什么会发生这种情况呢?

道听途说:FAB都GONE 掉了,就不跟踪Scroll状态了,所以也就没有 onNestedScroll() 什么事,但是INVISIBLE 就不同了,会很勤奋地做这件事情,虽然看不见。

 
comments powered by Disqus