使用Google Design Library如何在向下滚动时隐藏FAB按钮?

问题描述 投票:37回答:6

谷歌已经发布了我正在使用的设计库

 compile 'com.android.support:design:22.2.1'

但是,我无法看到任何代码示例如何使用此库以及如何在滚动上设置FAB栏的动画。我想我可以在ListView上监听滚动事件,然后自己动画按钮,但这不是API(这不是这个支持库的重点)。

有这样的例子吗?

android material-design android-design-library floating-action-button
6个回答
93
投票

如果你正在使用RecyclerView并且你正在寻找简单的东西,你可以试试这个:

    recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener(){
        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy){
            if (dy > 0)
                fabAddNew.hide();
            else if (dy < 0)
                fabAddNew.show();
        }
    });

通过用常数替换0,您可以调整触发的灵敏度,从而提供更流畅的体验


45
投票

使用自定义CoordinatorLayout.Behavior可以轻松完成组件对滚动事件的反应,因为当您覆盖onStartNestedScroll()时,它们会自动接收滚动事件。

示例行为隐藏并显示在此FABAwareScrollingViewBehavior中找到的滚动上的FAB,构建于cheesesquare之上:

public class FABAwareScrollingViewBehavior
    extends AppBarLayout.ScrollingViewBehavior {
  public FABAwareScrollingViewBehavior(Context context, AttributeSet attrs) {
    super(context, attrs);
  }

  @Override
  public boolean layoutDependsOn(CoordinatorLayout parent,
      View child, View dependency) {
    return super.layoutDependsOn(parent, child, dependency) ||
            dependency instanceof FloatingActionButton;
  }

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

  @Override
  public void onNestedScroll(
      final CoordinatorLayout coordinatorLayout, final View child,
      final View target, final int dxConsumed, final int dyConsumed,
      final int dxUnconsumed, final int dyUnconsumed) {
    super.onNestedScroll(coordinatorLayout, child, target,
      dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed);
    if (dyConsumed > 0) {
      // User scrolled down -> hide the FAB
      List<View> dependencies = coordinatorLayout.getDependencies(child);
      for (View view : dependencies) {
        if (view instanceof FloatingActionButton) {
          ((FloatingActionButton) view).hide();
        }
      }
    } else if (dyConsumed < 0) {
      // User scrolled up -> show the FAB
      List<View> dependencies = coordinatorLayout.getDependencies(child);
      for (View view : dependencies) {
        if (view instanceof FloatingActionButton) {
          ((FloatingActionButton) view).show();
        }
      }
    }
  }
}

你的滚动视图将有app:layout_behavior="com.support.android.designlibdemo.FABAwareScrollingViewBehavior"而不是app:layout_behavior="@string/appbar_scrolling_view_behavior"

但是,如果你愿意,你可以用任何动作替换hide()show()。有关如何做到这一点的详细信息可以在this postfollow up post for v22.2.1以及follow up post for v25.1.0中找到。

请注意,这与设计库的所有滚动行为一样,要求您的视图支持嵌套滚动,目前将限制为NestedScrollViewRecyclerView - ListViewScrollView仅适用于API21 +设备。


8
投票

如果你没有使用RecycleView(也就是普通的ScrollView),那么这就可以了:

mScrollView.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {
        @Override
        public void onScrollChanged() {
            if (mScrollView.getScrollY() > oldScrollYPostion) {
                fab.hide();
            } else if (mScrollView.getScrollY() < oldScrollYPostion || mScrollView.getScrollY() <= 0) {
                fab.show();
            }
            oldScrollYPostion = mScrollView.getScrollY();
        }
    });

别忘了申报:

private int oldScrollYPostion = 0;

在你的课堂里。


2
投票

使用CoordinatorLayout是最好的方法。但是,如果您想将侦听器附加到ListView或RecyclerView,您也可以这样做。我认为更可定制。这是我在git hub上的例子。

Github Project: Hide FAB(material Library) with listview

enter image description here


2
投票

@ianhanniballake工作正常,但方法onStartNestedScroll()onNestedScroll()已被弃用。这是更新版本:

public class FabAwareScrollingViewBehavior extends AppBarLayout.ScrollingViewBehavior {

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

    @Override
    public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) {
        return super.layoutDependsOn(parent, child, dependency) ||
                dependency instanceof FloatingActionButton;
    }

    @Override
    public boolean onStartNestedScroll(@NonNull CoordinatorLayout coordinatorLayout,
                                       @NonNull View 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, type);
    }

    @Override
    public void onNestedPreScroll(@NonNull CoordinatorLayout coordinatorLayout,
                                  @NonNull View child, @NonNull View target, int dx, int dy,
                                  @NonNull int[] consumed, int type) {
        super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed, type);

        if (dy > 0) {
            // User scrolled down -> hide the FAB
            List<View> dependencies = coordinatorLayout.getDependencies(child);
            for (View view : dependencies) {
                if (view instanceof FloatingActionButton) {
                    ((FloatingActionButton) view).hide();
                }
            }
        } else if (dy < 0) {
            // User scrolled up -> show the FAB
            List<View> dependencies = coordinatorLayout.getDependencies(child);
            for (View view : dependencies) {
                if (view instanceof FloatingActionButton) {
                    ((FloatingActionButton) view).show();
                }
            }
        }
    }
}

@ianhanniballake也有一篇关于这个主题的非常好的帖子:Intercepting everything with CoordinatorLayout Behaviors


2
投票
recyclerView.setOnFlingListener(new RecyclerView.OnFlingListener() {
    @Override
    public boolean onFling(int velocityX, int velocityY) {
        if (velocityY < 0)
            mScrollCallbacks.showUI();
            //Code to hide the UI, I have  a custom one that slides down the nav  bar and the fab
        else if (velocityY > 0)
            mScrollCallbacks.hideUI();
            //Code to show the UI

        return false;
    }
});

这非常有效

© www.soinside.com 2019 - 2024. All rights reserved.