本文原做者 Saket Narayan,文章翻译自做者我的博客 Introducing InboxRecyclerView, a library for building expandable descendant navigation。项目Github传送门。html
InboxRecyclerView是一款基于RecyclerView的开源控件,支持点击时展开以及下拉折叠的动画切换效果。 java
若是你有兴趣了解InboxRecyclerView的工做原理感兴趣,下文将对项目的一些细节进行描述。android
InboxRecyclerView包含主要两部分:列表项的InboxRecyclerView
以及用于显示可扩展内容的ExpandablePageLayout
。单击某个项目时InboxRecyclerView将执行三个步骤:git
1. 准备展开 InboxRecyclerView将详细内容与列表项对齐。在展开的过程当中,列表项(ListItem)和内容项(Content)同时进行淡出淡如操做,使列表项看起来自身正在展开。 github
val itemLocation: Rect = captureViewLocation(clickedItem)
contentPage.visibility = View.VISIBLE
contentPage.translationY = itemLocation.y
contentPage.setDimensions(itemLocation.width, itemLocation.height)
复制代码
此时,该列表项的详细内容将被加载入ExpandablePageLayout
中,具体内容请参考示例程序ide
2. 展开列表项 在对齐列表项和内容项后,下一步是为展开设置动画效果。为了保证展开动画流畅,InboxRecyclerView使用View#setClippedBounds(Rect)对View的可见部分进行动画处理,以营造一种它正在展开的错觉。 动画
fun animateDimensions(toWidth: Int, toHeight: Int) {
val fromWidth = clipBounds.width()
val fromHeight = clipBounds.height()
ObjectAnimator.ofFloat(0F, 1F)
.addUpdateListener {
val scale = it.animatedValue as Float
val newWidth = (toWidth - fromWidth) * scale + fromWidth
val newHeight = (toHeight - fromHeight) * scale + fromHeight)
contentPage.clipBounds = Rect(0, 0, newWidth, newHeight)
}
.start()
}
复制代码
3.给列表项添加动画效果 为了实现展开内容正在推开其余列表项的动画效果,在动画期间其余项目也会随着被展开的内容同步移动。这在ItemExpandAnimator内实现,固然,展开动画支持自定义。 ui
Pull to Collapse的手势动做利用了Android View的特性:ViewGroup能够先于子View拦截触摸事件,详细的内容请参考做者的另外一篇文章:Designing a flick dismissible image viewer(计划会在以后翻译)。 spa
override fun onTouch(view, event): Boolean {
when (event.action) {
ACTION_MOVE -> {
val deltaY = event.rawY - lastTouchY
val friction = 4F
var deltaYWithFriction = deltaY / frictionFactor
view.translationY += deltaYWithFriction
val lastTouchY = event.rawY
}
ACTION_UP -> {
if (isEligibleForCollapse()) {
collapsePage()
} else {
smoothlyResetPage()
}
}
}
}
复制代码
一旦页面滚动超出了它的移动范围,这个摩擦力将会变得很是大,从而产生以下效果: 翻译
if (isEligibleForCollapse()) {
val extraFriction = collapseDistanceThreshold / view.translationY
deltaYWithFriction *= extraFriction
}
复制代码
InboxRecyclerView用白色覆盖了ListView的不可见部分,在下拉折叠的过程当中,这层白色会逐渐淡出以显示被覆盖的内容,从而强调了下拉的动画效果。
这是我翻译的第一篇有关开源控件的博客,但愿各位喜欢。
若是对个人文章感兴趣,请移驾轻量级自定义NumberPicker(给我个星吧求求大家了,Github传送门)
总而言之,千山万水老是情,点个赞再走呗。