-
Notifications
You must be signed in to change notification settings - Fork 2
/
HighLightRecyclerView.kt
107 lines (101 loc) · 4.38 KB
/
HighLightRecyclerView.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
class HighLightRecyclerView(context: Context, attr: AttributeSet?) : RecyclerView(context, attr) {
constructor(context: Context) : this(context, null)
lateinit var animator: ValueAnimator
private var hasHighLightHeightInitialized = false
var highLightHeight: Int = 0
set(value) {
field = value
postInvalidateOnAnimation()
}
var paint = Paint()
var path = Path()
init {
paint.style = Paint.Style.FILL
paint.color = Color.parseColor("#99000000")
// addDecoration
val decoration = object : RecyclerView.ItemDecoration() {
override fun getItemOffsets(
outRect: Rect,
view: View,
parent: RecyclerView,
state: State
) {
super.getItemOffsets(outRect, view, parent, state)
[email protected]?.let {
if (parent.getChildAdapterPosition(view) == 0)
outRect.top = (parent.measuredHeight - view.layoutParams.height).shr(1)
else if (parent.getChildAdapterPosition(view) == it.itemCount - 1)
outRect.bottom = (parent.measuredHeight - view.layoutParams.height).shr(1)
}
}
}
addItemDecoration(decoration)
// attach SnapHelper
val snapHelper = object : LinearSnapHelper() {
override fun findSnapView(layoutManager: RecyclerView.LayoutManager?): View? {
return when {
layoutManager == null -> null
layoutManager.childCount == 0 -> null
else -> {
var closestChild: View? = null
var absClosest = Int.MAX_VALUE
val helper = OrientationHelper.createVerticalHelper(layoutManager)
val center = helper.startAfterPadding + helper.totalSpace.shr(1)
var childCenter: Int
var distance: Int
for (i in 0 until layoutManager.childCount) {
layoutManager.getChildAt(i)?.let {
childCenter = if (i == 0)
helper.getDecoratedStart(it) + helper.getDecoratedMeasurement(it) - it.layoutParams.height
else helper.getDecoratedStart(it) + it.layoutParams.height.shr(1)
distance = abs(center - childCenter)
if (distance < absClosest) {
absClosest = distance
closestChild = it
}
}
}
closestChild
}
}
}
}
addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
super.onScrollStateChanged(recyclerView, newState)
if (newState == SCROLL_STATE_IDLE) {
snapHelper.findSnapView(layoutManager)?.let {
animator = ValueAnimator.ofInt(highLightHeight, it.layoutParams.height)
.setDuration(300)
animator.removeAllUpdateListeners()
animator.addUpdateListener { va ->
highLightHeight = va.animatedValue as Int
}
animator.start()
}
}
}
})
hasFixedSize()
snapHelper.attachToRecyclerView(this)
}
fun initHighLightHeight(initialHeight: Int) {
if (!hasHighLightHeightInitialized) {
highLightHeight = initialHeight
hasHighLightHeightInitialized = true
}
}
override fun onDrawForeground(canvas: Canvas?) {
super.onDrawForeground(canvas)
path.reset()
path.addRect(0f, 0f, width.toFloat(), height.toFloat(), Path.Direction.CW)
path.addRect(
0f,
(height - highLightHeight).shr(1).toFloat(),
width.toFloat(),
(height + highLightHeight).shr(1).toFloat(),
Path.Direction.CCW
)
canvas?.drawPath(path, paint)
}
}