本文原做者 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的不可見部分,在下拉摺疊的過程當中,這層白色會逐漸淡出以顯示被覆蓋的內容,從而強調了下拉的動畫效果。
使用這個,App能夠變得很是有創意。好比 Dank,使用狀態欄去指示內容是否可摺疊。這是我翻譯的第一篇有關開源控件的博客,但願各位喜歡。
若是對個人文章感興趣,請移駕輕量級自定義NumberPicker(給我個星吧求求大家了,Github傳送門)
總而言之,千山萬水老是情,點個贊再走唄。