滚动时在 NestedScrollView 中隐藏 FAB

Hide FAB in NestedScrollView when scrolling

我有一个嵌套滚动视图,其中包含一些线性布局和文本视图之类的内容。 出于某些原因,我也在使用 floatingactionbutton 库。所以我不能为它使用任何行为。 我不知道我应该如何处理来自 scrollview 的 scrollchangelistener 以像行为一样动态地隐藏和显示 fab。

关于如何在滚动时隐藏和显示 fab 有什么建议吗?

创建 FabScrollBehavior class

public class FabScrollBehavior extends CoordinatorLayout.Behavior<FloatingActionButton> {
    private int toolbarHeight;

    public FabScrollBehavior(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.toolbarHeight = AppUtil.getToolbarHeight(context);
    }

    @Override
    public boolean layoutDependsOn(CoordinatorLayout parent, FloatingActionButton fab, View dependency) {
        return dependency instanceof AppBarLayout;
    }

    @Override
    public boolean onDependentViewChanged(CoordinatorLayout parent, FloatingActionButton fab, View dependency) {
        if (dependency instanceof AppBarLayout) {
            CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams) fab.getLayoutParams();
            int fabBottomMargin = lp.bottomMargin;
            int distanceToScroll = fab.getHeight() + fabBottomMargin;
            float ratio = (float)dependency.getY()/(float)toolbarHeight;
            fab.setTranslationY(-distanceToScroll * ratio);
        }
        return true;
    }
}

其中 AppUtil.getToolbarHeight(上下文)是 -

public static int getToolbarHeight(Context context) {
        final TypedArray styledAttributes = context.getTheme().obtainStyledAttributes(
                new int[]{R.attr.actionBarSize});
        int toolbarHeight = (int) styledAttributes.getDimension(0, 0);
        styledAttributes.recycle();

        return toolbarHeight;
    }

然后在您的布局中添加到 FloatingActionButton layout_behavior:

   <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab_task_accept"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="end|bottom"
        android:layout_margin="@dimen/fab_margin"
        android:src="@drawable/ic_accepted"
        app:layout_behavior="pass.to.your.FabScrollBehavior.Class"
        app:theme="@style/Widget.AppTheme.Fab"/>

整个布局看起来像

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:animateLayoutChanges="true"
    android:orientation="vertical">

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/Widget.AppTheme.AppBarOverlay">

        <include
            layout="@layout/include_layout_toolbar_scroll"/>

    </android.support.design.widget.AppBarLayout>


    <include layout="@layout/include_layout_content_with_nestedscroll"/>

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab_task_accept"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="end|bottom"
        android:layout_margin="@dimen/fab_margin"
        android:src="@drawable/ic_accepted"
        app:layout_behavior="pass.to.FabScrollBehavior.Class"
        app:theme="@style/Widget.AppTheme.Fab"/>


</android.support.design.widget.CoordinatorLayout>

https://mzgreen.github.io/2015/02/15/How-to-hideshow-Toolbar-when-list-is-scroling(part1)/

实施

只需将下面的代码添加到您的 NestedScrollView ScrollChangeListener 中:

NestedScrollView nsv = v.findViewById(R.id.nsv);
    nsv.setOnScrollChangeListener(new NestedScrollView.OnScrollChangeListener() {
        @Override
        public void onScrollChange(NestedScrollView v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {
            if (scrollY > oldScrollY) {
                fab.hide();
            } else {
                fab.show();
            }
        }
    });

在你的 Activity 或片段中定义变量类型 int 以设置来自 ScrollView 的上一个 Scroll 然后使用此方法来监听 ScrollView 中的变化滚动 Class

 scrollView.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {
        @Override
        public void onScrollChanged() {

    // previousScrollY this variable is define in your Activity or Fragment
            if (scrollView.getScrollY() > previousScrollY && floatingActionButton.getVisibility() == View.VISIBLE) {
                floatingActionButton.hide();
            } else if (scrollView.getScrollY() < previousScrollY && floatingActionButton.getVisibility() != View.VISIBLE) {
                floatingActionButton.show();
            }
            previousScrollY = scrollView.getScrollY();
        }
    });

将完成 android

的所有版本

经过这么长时间我找到了解决办法。 它可能适用于所有情况。虽然这不是正确的解决方案,但你可以应用它来使这个东西工作。

据我们所知,setOnScrollChangeListener 仅在最低 api 23 时有效,所以如果我的最低 api 水平低于 23 怎么办。

所以我从堆栈溢出中找到了我们可以使用的解决方案 getViewTreeObserver().addOnScrollChangedListener 所以这将是所有设备的兼容解决方案。

现在让我们进入问题的最终解决方案"Hide fab button when nested scroll view scrolling and Show fab button when nested scroll view in ideal state"

因此我们可以使用 HandlerpostDelayed 来解决这个问题。

  1. 在您的上下文中定义变量 private int previousScrollY = 0;

  2. 然后像这样使用 getViewTreeObserver().addOnScrollChangedListener 到你的嵌套滚动视图。

NESTEDSCROLLVIEW.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() { @Override public void onScrollChanged() { new Handler().postDelayed(new Runnable() { @Override public void run() { if (NESTEDSCROLLVIEW.getScrollY() == previousScrollY) { FABBUTTON.setVisibility(View.VISIBLE); } else { FABBUTTON.setVisibility(View.INVISIBLE); } } }, 10); previousScrollY = NESTEDSCROLLVIEW.getScrollY(); } });

  1. 现在您可以开始了....

您可以使用此侦听器在滚动时观察和隐藏 FAB。

   nestedScrollView.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {
                @Override
                public void onScrollChanged() {
                    if (nestedScrollView != null) {
                        if (nestedScrollView.getChildAt(0).getBottom() <= (nestedScrollView.getHeight() + nestedScrollView.getScrollY())) {
                            fab.setVisibility(View.INVISIBLE);
                        } else {
                            fab.setVisibility(View.VISIBLE);
                        }
                    }
                }
            });