-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathViews.kt
131 lines (115 loc) · 3.79 KB
/
Views.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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
package mvil
import android.app.Activity
import android.content.Context
import android.view.View
import android.view.ViewGroup
import android.view.ViewTreeObserver
import android.widget.FrameLayout
import android.widget.ImageView
import kotlin.math.max
import kotlin.math.min
typealias RealisedView = View
fun realiseView(activity: Context, parent: ViewGroup, virtual: Virtual, index: Int): View {
val view = virtual.cls(activity)
parent.addView(view, index)
return view
}
fun removeChild(view: View) {
val vg = (view.parent as? ViewGroup)
if (vg != null) {
vg.removeView(view)
}
}
fun removeChild(parentView: ViewGroup, childView: View) {
parentView.removeView(childView)
removeViewCache(childView)
}
fun reOrderChild(child: View, i: Int) {
val vg = (child.parent as? ViewGroup)
if (vg != null) {
vg.removeView(child)
vg.addView(child, min(i, vg.childCount))
}
}
fun pop(many: MutableList<View>): View? {
if (many.size == 0){
return null
}
val popped = many.get(0)
many.removeAt(0)
return popped
}
fun orderAndCullViews(activity: Context, parentView: ViewGroup,
virtualChildren: List<Virtual>): List<View?> {
val childrenHaveTags = virtualChildren.all {it.tag != ""}
if (childrenHaveTags) {
val allChildren = getChildren(parentView)
val taggedChildren = virtualChildren.mapIndexed { i, vChild ->
val foundChild = allChildren.find { rChild ->
vChild.tag != "" && vChild.tag == rChild?.tag
}
foundChild
}
allChildren.filter {! taggedChildren.contains(it)}.forEach {
// This is where child views are removed when tagged views
// disappear.
removeChild(it!!)
}
return taggedChildren
}
// When there are NO tags:
// - excess child views are removed
// - views are deleted if virtual and real class do not match
deleteExcessChildren(parentView, virtualChildren)
deleteUnmatchedRealAndVirtualClass(parentView, virtualChildren.map {
it.cls(activity)
})
return getChildren(parentView, virtualChildren.size)
}
fun getChildren(viewGroup: ViewGroup): List<View> {
return (0..viewGroup.childCount-1).map {i ->
viewGroup.getChildAt(i)
}
}
fun getChildren(viewGroup: ViewGroup, expectedLength: Int): List<View?> {
return (0..expectedLength-1).map {i ->
viewGroup.getChildAt(i)
}
}
fun deleteUnmatchedRealAndVirtualClass(realParent: ViewGroup,
virtualChildren: List<RealisedView>) {
getChildren(realParent).zip(virtualChildren).forEach {(real, realised) ->
if (real::class != realised::class) {
removeChild(realParent, real)
}
}
}
fun deleteExcessChildren(rootView: ViewGroup, virtuals: List<Virtual>) {
val rsize: Int = rootView.childCount
val vsize = virtuals.size
val excessSize = max(rsize-vsize, 0)
for (i in (rsize-excessSize)..(rsize-1)) {
val child = rootView.getChildAt(i)
// Child can be null when deleteExcessChildren has already run
// for parent's children
removeChild(rootView, child)
}
}
class RenderView(val activity: Activity): FrameLayout(activity) {
fun sync(virtual: Virtual) {
render(activity, this, arrayListOf(virtual))
}
}
class StatefulImageView(val activity: Context): ImageView(activity) {
var layoutBottom: Int = 0
var layoutRight: Int = 0
init {
viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
override fun onGlobalLayout() {
layoutBottom = bottom
layoutRight = right
viewTreeObserver.removeOnGlobalLayoutListener(this)
}
})
}
}