Behavior实现滑动隐藏ToolBar与BottomNavigation

    xiaoxiao2021-03-25  119

    多说无益,先上效果图img\material-design

    这个效果其实是和SegmentFault的首页效果是一样的。

    Demo github地址戳这里

    来由

    前几天有人问我这样的效果如何实现,有何思路,我的第一反应就是使用Behavior来实现这个效果,使用Behavior实现此效果比自定义View实现此效果绝对要简单很多,之后找时间了实现了这个效果。

    思路

    用过ToolBar + CoordinatorLayout + AppBarLayout的人应该知道这三者组合使用再设置合适的参数(没用过的人赶紧去看看吧,或者看我的Demo也可以哟),就可以实现滑动隐藏显示ToolBar,因此这部分的效果Android使用Behavior已经替我们实现好了,没必要再去费神了,而且它的效果也蛮不错。

    接下来我们要考虑的就是如何实现在滑动的时候也隐藏底部的BottomNavigation,既然前面我已经说过用Behavior来实现此效果,因此我们需要自定义一个Behavior来实现滑动隐藏BottomNavigation。

    撸代码

    在前面一篇文章自定义Behavior实现快速返回效果(没看过的请先看看)中我已经介绍了自定义Behavior的相关知识,这里就不再赘述了。

    先来看看ToolBar滑动隐藏的代码

    <?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.support.design.widget.AppBarLayout android:id="@+id/appBarLayout" android:layout_width="match_parent" android:layout_height="wrap_content" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"> <android.support.v7.widget.Toolbar android:id="@+id/toolBar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="@android:color/holo_blue_dark" app:title="ToolBar Title" app:titleTextColor="@android:color/white" app:layout_scrollFlags="scroll|enterAlways"/> </android.support.design.widget.AppBarLayout> </android.support.design.widget.CoordinatorLayout>

    上面属性设置中app:layout_scrollFlags="scroll|enterAlways"这个是必须要有,否则话滑动的时候ToolBar是不会滑动的。

    那滑动隐藏BottomNavigation的这个Behavior该如何实现呢?其实很简单,我们在滑动列表的时候可以看到当ToolBar往上滑的时候BottomNavigation会同时往下滑,因此这里我可以把ToolBar作为BottomNavigation的依赖,ToolBar往上滑动多少BottomNavigation就同时往下滑动多少(这里我实现时保证了两者高度一致)。

    既然知道了依赖关系也知道了滑动方向和滑动距离,再实现Behavior就简单多了,代码如下:

    public class BottomNavigationViewBehavior extends CoordinatorLayout.Behavior<View> { public BottomNavigationViewBehavior() { } public BottomNavigationViewBehavior(Context context, AttributeSet attrs) { super(context, attrs); } @Override public boolean onLayoutChild(CoordinatorLayout parent, View child, int layoutDirection) { ((CoordinatorLayout.LayoutParams) child.getLayoutParams()).topMargin = parent.getMeasuredHeight() - child.getMeasuredHeight(); return super.onLayoutChild(parent, child, layoutDirection); } @Override public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) { //因为Behavior只对CoordinatorLayout的直接子View生效,因此将依赖关系转移到AppBarLayout return dependency instanceof AppBarLayout; } @Override public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) { //得到依赖View的滑动距离 int top = ((AppBarLayout.Behavior)((CoordinatorLayout.LayoutParams)dependency.getLayoutParams()).getBehavior()).getTopAndBottomOffset(); //因为BottomNavigation的滑动与ToolBar是反向的,所以取-top值 ViewCompat.setTranslationY(child, -top); return false; } }

    上面的代码中获取依赖视图AppBarLayout的滑动距离时需要注意几点: 1. 通过AppBarLayout.getTranslationY()无法获取到正确的滑动距离 2. 通过AppBarLayout.getTop()无法获取到正确的滑动距离 3. 最后查看源码后发现通过AppBarLayout.Behavior.getTopAndBottomOffset()可以获得正确的滑动距离值

    现在Behavior实现了,我们再来看完整的布局文件

    <?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.support.design.widget.AppBarLayout android:id="@+id/appBarLayout" android:layout_width="match_parent" android:layout_height="wrap_content" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"> <android.support.v7.widget.Toolbar android:id="@+id/toolBar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="@android:color/holo_blue_dark" app:title="ToolBar Title" app:titleTextColor="@android:color/white" app:layout_scrollFlags="scroll|enterAlways"/> <android.support.design.widget.TabLayout android:id="@+id/tabLayout" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@android:color/holo_blue_light" app:tabTextColor="@android:color/white" app:tabGravity="center" app:tabIndicatorColor="@android:color/white" app:tabSelectedTextColor="@android:color/holo_red_dark"/> </android.support.design.widget.AppBarLayout> <android.support.v4.view.ViewPager android:id="@+id/viewpager" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@android:color/white" app:layout_behavior="@string/appbar_scrolling_view_behavior"/> <android.support.design.widget.BottomNavigationView android:id="@+id/bottomNavigationView" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="@android:color/holo_blue_dark" android:layout_gravity="bottom" app:menu="@menu/bottom_menus" app:layout_behavior="cn.ittiger.stickynavigation.behavior.BottomNavigationViewBehavior" /> </android.support.design.widget.CoordinatorLayout>

    对于布局中的ToolBar和BottomNavigationView也可以换成其他任意View来实现滑动隐藏效果。

    Demo的完整代码在这 github地址

    转载请注明原文地址: https://ju.6miu.com/read-13465.html

    最新回复(0)