-
Notifications
You must be signed in to change notification settings - Fork 3
/
EmitExpandableTransformationBehavior.kt
130 lines (119 loc) · 4.32 KB
/
EmitExpandableTransformationBehavior.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
package com.paranoid.mao.expandablewidgetexample
import android.animation.*
import android.content.Context
import android.util.AttributeSet
import android.view.View
import android.view.ViewGroup
import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.core.animation.addListener
import androidx.core.view.children
import androidx.core.view.isInvisible
import androidx.core.view.isVisible
import com.google.android.material.floatingactionbutton.FloatingActionButton
import com.google.android.material.transformation.ExpandableTransformationBehavior
import java.util.ArrayList
class EmitExpandableTransformationBehavior @JvmOverloads constructor(
context: Context? = null,
attrs: AttributeSet? = null
) : ExpandableTransformationBehavior(context, attrs) {
companion object {
private const val EXPAND_DELAY = 60L
private const val EXPAND_DURATION = 150L
private const val COLLAPSE_DELAY = 60L
private const val COLLAPSE_DURATION = 150L
}
override fun layoutDependsOn(parent: CoordinatorLayout, child: View, dependency: View): Boolean {
return dependency is FloatingActionButton && child is ViewGroup
}
override fun onCreateExpandedStateChangeAnimation(
dependency: View,
child: View,
expanded: Boolean,
isAnimating: Boolean
): AnimatorSet {
if (child !is ViewGroup) {
return AnimatorSet()
}
val animations = ArrayList<Animator>()
if (expanded) {
createExpandAnimation(child, isAnimating, animations)
} else {
createCollapseAnimation(child, animations)
}
val set = AnimatorSet()
set.playTogether(animations)
set.addListener(
onStart = {
if (expanded) {
child.isVisible = true
}
},
onEnd = {
if (!expanded) {
child.isInvisible = true
}
}
)
return set
}
private fun createExpandAnimation(
child: ViewGroup,
currentlyAnimating: Boolean,
animations: MutableList<Animator>
) {
if (!currentlyAnimating) {
child.children.forEach {
it.alpha = 0f
it.scaleX = 0.4f
it.scaleY = 0.4f
}
}
val delays = List(child.childCount) {
it * EXPAND_DELAY
}.reversed().asSequence()
val scaleXHolder = PropertyValuesHolder.ofFloat(View.SCALE_X, 1f)
val scaleYHolder = PropertyValuesHolder.ofFloat(View.SCALE_Y, 1f)
val alphaHolder = PropertyValuesHolder.ofFloat(View.ALPHA, 1f)
val animators = child.children.zip(delays) { view, delay ->
ObjectAnimator.ofPropertyValuesHolder(
view,
scaleXHolder,
scaleYHolder,
alphaHolder
).apply {
duration = EXPAND_DURATION
startDelay = delay
}
}.toList()
val animatorSet = AnimatorSet().apply {
playTogether(animators)
}
animations.add(animatorSet)
}
private fun createCollapseAnimation(
child: ViewGroup,
animations: MutableList<Animator>
) {
val delays = List(child.childCount) {
it * COLLAPSE_DELAY
}.asSequence()
val scaleXHolder = PropertyValuesHolder.ofFloat(View.SCALE_X, 0.4f)
val scaleYHolder = PropertyValuesHolder.ofFloat(View.SCALE_Y, 0.4f)
val alphaHolder = PropertyValuesHolder.ofFloat(View.ALPHA, 0f)
val animators = child.children.zip(delays) { view, delay ->
ObjectAnimator.ofPropertyValuesHolder(
view,
scaleXHolder,
scaleYHolder,
alphaHolder
).apply {
duration = COLLAPSE_DURATION
startDelay = delay
}
}.toList()
val animatorSet = AnimatorSet().apply {
playTogether(animators)
}
animations.add(animatorSet)
}
}