Behavior实现滑动隐藏ToolBar与BottomNavigation

来源:互联网 发布:单片机与嵌入式的联系 编辑:程序博客网 时间:2024/04/27 10:32

多说无益,先上效果图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>

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

Demo的完整代码在这 github地址

0 0
原创粉丝点击