我有一个recyclerView
可以水平滚动。每个视图都会自动对齐到屏幕中心。为了实现这个功能,我使用了LinearSnapHelper。这个工具已经很好地解决了问题。
唯一的问题出现在recyclerview的第一个和最后一个项上。当您向开始位置滚动时,它们没有对齐到中心。如果在滚动之前检查recyclerview状态,您可以看到第一个项位于屏幕中央的正确位置。我通过添加我的自定义ItemOffsetDecoration实现了这一点。基于显示器的宽度和视图本身,我为最后和第一个视图添加了额外的填充,以便将其定位到中间位置。
问题是,如果您滚动recyclerview并将其向前滚动到开始或结束位置,则这些视图不会自动对齐到中间位置。看起来LinearSnapHelper无法检测到它们已经被对齐到中心。
RecyclerViewInit:
timelineSnapHelper = LinearSnapHelper()
timelineViewManager = LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)
timelineViewAdapter = TimelineListAdapter(timelineViewManager, timelineList, this)
timelineOffsetDecoration = ItemOffsetDecoration(context!!, 32, 45)
timelineRecyclerView = view.findViewById<RecyclerView>(R.id.timeline_recycler_view).apply {
layoutManager = timelineViewManager
adapter = timelineViewAdapter
addItemDecoration(timelineOffsetDecoration)
setHasFixedSize(true)
}
timelineSnapHelper.attachToRecyclerView(timelineRecyclerView)
timelineRecyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrollStateChanged(recyclerView: RecyclerView?, newState: Int) {
if (newState == AbsListView.OnScrollListener.SCROLL_STATE_IDLE) {
val centerView = timelineSnapHelper.findSnapView(timelineRecyclerView.layoutManager)
val anim = AnimationUtils.loadAnimation(context, R.anim.scale_timeline_start)
centerView!!.startAnimation(anim)
anim.fillAfter = true
lastSnappedTime = centerView
} else if (lastSnappedTime != null){
lastSnappedTime = null
}
if(newState == AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL && lastSnappedTime != null){
val anim = AnimationUtils.loadAnimation(context, R.anim.scale_timeline_end)
lastSnappedTime!!.startAnimation(anim)
anim.fillAfter = true
}
}
})
自定义ItemDecoration:
class ItemOffsetDecoration(private val context: Context, private val edgePadding: Int, private var viewWidth: Int): RecyclerView.ItemDecoration() {
override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State?) {
super.getItemOffsets(outRect, view, parent, state)
val itemCount = state!!.itemCount
val itemPosition = parent.getChildAdapterPosition(view)
// no position, leave it alone
if (itemPosition == RecyclerView.NO_POSITION) {
return
}
val displayMetrics = context.resources.displayMetrics
val displayWidth: Int = displayMetrics.widthPixels
val viewPixelWidth: Int = (viewWidth * (displayMetrics.densityDpi / 160f)).toInt()
val startEndPadding: Int = (displayWidth - viewPixelWidth) / 2
// first item
if (itemPosition == 0) {
outRect.set(startEndPadding, edgePadding, edgePadding, edgePadding)
}
// last item
else if (itemCount > 0 && itemPosition == itemCount - 1) {
outRect.set(edgePadding, edgePadding, startEndPadding, edgePadding)
}
// every other item
else {
outRect.set(edgePadding, edgePadding, edgePadding, edgePadding)
}
}
}
应用程序问题的简短预览(我还需要修复一些动画错误:D
):