-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathLoopHorizontalLayoutManager
128 lines (114 loc) · 4.07 KB
/
LoopHorizontalLayoutManager
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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
import android.content.Context
import android.graphics.Color
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.Recycler
class LoopHLayoutManager(context: Context) : LinearLayoutManager(context) {
init {
orientation = HORIZONTAL
}
override fun generateDefaultLayoutParams(): RecyclerView.LayoutParams {
return RecyclerView.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT
)
}
override fun canScrollHorizontally(): Boolean {
return true
}
override fun canScrollVertically(): Boolean {
return false
}
override fun onLayoutChildren(recycler: RecyclerView.Recycler, state: RecyclerView.State) {
if (itemCount <= 0) {
return
}
if (state.isPreLayout) {
return
}
detachAndScrapAttachedViews(recycler)
var realWidth = 0
for (i in 0..itemCount) {
val itemView = recycler.getViewForPosition(i)
addView(itemView)
measureChildWithMargins(itemView, 0, 0)
val width = getDecoratedMeasuredWidth(itemView)
val height = getDecoratedMeasuredHeight(itemView)
layoutDecorated(itemView, realWidth, 0, realWidth + width, height)
realWidth += width
if (realWidth > getWidth()) {
break
}
}
}
override fun scrollHorizontallyBy(
dx: Int,
recycler: RecyclerView.Recycler,
state: RecyclerView.State
): Int {
val travl = fill(dx, recycler, state)
if (travl == 0) return 0
offsetChildrenHorizontal(-travl)
recyclerHideView(dx, recycler, state)
return travl
}
private fun fill(dx: Int, recycler: Recycler, state: RecyclerView.State): Int {
var xDistance = dx
if (xDistance > 0) {
val lastView = getChildAt(childCount - 1) ?: return 0
val lastPos = getPosition(lastView)
if (lastView.right < width) {
var scrap: View? = null
scrap = if (lastPos == itemCount - 1) {
recycler.getViewForPosition(0)
} else {
recycler.getViewForPosition(lastPos + 1)
}
addView(scrap)
measureChildWithMargins(scrap, 0, 0)
val width = getDecoratedMeasuredWidth(scrap)
val height = getDecoratedMeasuredHeight(scrap)
layoutDecorated(
scrap, lastView.right, 0,
lastView.right + width, height
)
return xDistance
}
} else {
val firstView = getChildAt(0) ?: return 0
val firstPos = getPosition(firstView)
if (firstView.left >= 0) {
val scrap: View = if (firstPos == 0) {
recycler.getViewForPosition(itemCount - 1)
} else {
recycler.getViewForPosition(firstPos - 1)
}
addView(scrap, 0)
measureChildWithMargins(scrap, 0, 0)
val width = getDecoratedMeasuredWidth(scrap)
val height = getDecoratedMeasuredHeight(scrap)
layoutDecorated(
scrap, firstView.left - width, 0,
firstView.left, height
)
}
}
return xDistance
}
private fun recyclerHideView(dx: Int, recycler: Recycler, state: RecyclerView.State) {
for (i in 0 until childCount) {
val view = getChildAt(i) ?: continue
if (dx > 0) {
if (view.right < 0) {
removeAndRecycleView(view, recycler)
}
} else {
if (view.left > width) {
removeAndRecycleView(view, recycler)
}
}
}
}
}