在这篇文章当中我们将会介绍如何完成在Google+上看到的当列表向下滑动时隐藏Toolbar或其他视图,而当向上滑动时又显示出来的效果。这个效果在 Material Design Checklist上有提及.
我们将使用RecyclerView来作为列表视图,但在其他可滑动容器上都是可以实现的(比如在listview上需要一些其他工作)。要实现这个效果有两个思路:
1 给列表添加padding
2 给列表添加header
我决定用第二种方式来实现,因为在添加一个header到recyclerView的过程中我看到过很多问题,我想这是一个好机会来普及这个地方的知识当然我也会简要介绍第一种方式。
开始
首先我们需要创建工程添加一些基本类库:
1 styles.xml定义主题。
2 activity 布局,RecyclerView
, Toolbar
和 ImageButton
会被放进一个FrameLayout因为Toolbar需要放在recyclerview上,如果不这样做在隐藏toolbar时会出现空白区域。
3 MainActivity:1)初始化toolbar,获取视图引用,初始化recyclerview,然后为其添加适配器及相应的ViewHolder。
此时运行会发现,当toolbar隐藏时,我们的列表项也回被隐藏,或许你已注意到我们使用的FrameLayout,这时就是我们前面所提到的两种解决方案,第一种是为recyclerview添加paddingTop,然后将这个值设置到toolbar得高度上,但同时需要将recyclerview的clipToPadding设置为true。这样效果就达到了。
第二种 添加header
首先我们需要修改适配器:
1 我们需要定义recycler的展示类型。recyclerview是一个很灵活的控件,item类型就是在你希望为一些列表项定制不同的布局时会用到的,而这就是我们要做的,我们的第一项和其余的项会使用不同的布局,因为第一项是header。
2 我们需要告诉recycler要展示的item类型。
3 我们需要修改 onCreateViewHolder
和 onBindViewHolder()
方法根据类型TYPE_ITEM和TYPE_HEAEDR的不同返回不同的项。
4 修改getItemCount(),应在原有个数上+1.
现在就可以为header建布局和viewholder了,需要注意的是其高度需要与toolbar的高度一致。
列表滚动时的视图展示和隐藏
要达到这个效果我们只需要对recyclerview的滚动进行监听,因此要写一个监听类OnScrollListener。
而这里不得不提到onScrolled方法,它的参数dx和dy并非是滑动距离而是指先后两次进入该方法的dx或dy的差值,即可以用它来判断滑动方向。
算法如下:
1 我们在视图隐藏向上滑或视图展示向下滑时才计算总的滑动距离,因为这两种情况才是我们的关注重点,一个是即将展示要作的处理一个是即将隐藏要作的处理。
2 如果总滑动距离超过了我们定义的临界值,此时我们就可以通过滑动方向来显示和隐藏视图了,dy>0代表向下滑,反之向上滑。
3 具体实现在调用者中。
大功告成:
看上去几乎完美了,但还有点问题,当滑动临界值较小时,隐藏toolbar会在列表顶部出现空白,这是因为列表的header在列表滑动时没有完全滑出屏幕而toolbar已经隐藏了,因此会看到那块预留的空白,所以在隐藏展示toolbar时还需要把header的显示情况加到逻辑里进去。
Source code of the full project described in this post is available on GitHubrepo.