1
+ package com.example.tutorial1_1basics.chapter3_physics
2
+
3
+ import android.animation.Animator
4
+ import android.animation.AnimatorListenerAdapter
5
+ import android.annotation.SuppressLint
6
+ import android.os.Bundle
7
+ import android.view.MotionEvent
8
+ import android.view.View
9
+ import android.view.ViewPropertyAnimator
10
+ import android.view.animation.AccelerateDecelerateInterpolator
11
+ import android.view.animation.Interpolator
12
+ import android.widget.Button
13
+ import androidx.appcompat.app.AppCompatActivity
14
+ import androidx.dynamicanimation.animation.DynamicAnimation
15
+ import androidx.dynamicanimation.animation.SpringAnimation
16
+ import androidx.dynamicanimation.animation.SpringForce
17
+ import androidx.interpolator.view.animation.FastOutLinearInInterpolator
18
+ import androidx.interpolator.view.animation.LinearOutSlowInInterpolator
19
+ import com.example.tutorial1_1basics.R
20
+ import com.google.android.material.floatingactionbutton.FloatingActionButton
21
+
22
+ class Activity3_5ElasticScale : AppCompatActivity () {
23
+
24
+ override fun onCreate (savedInstanceState : Bundle ? ) {
25
+ super .onCreate(savedInstanceState)
26
+ setContentView(R .layout.activity3_5elastic_scale)
27
+
28
+ val buttonScaleDown = findViewById<Button >(R .id.buttonScaleDown)
29
+ val buttonScaleUp = findViewById<Button >(R .id.buttonScaleUp)
30
+ val buttonScaleDownSpring = findViewById<Button >(R .id.buttonScaleDownSpring)
31
+ val buttonScaleUpSpring = findViewById<Button >(R .id.buttonScaleUpSpring)
32
+ val buttonElastic = findViewById<Button >(R .id.buttonElastic)
33
+
34
+ val fab = findViewById<FloatingActionButton >(R .id.floatingActionButton)
35
+
36
+ buttonScaleDown.setOnClickListener {
37
+
38
+ val animator = buttonScaleDown.animate()
39
+ .scaleX(.9f )
40
+ .scaleY(.9f )
41
+ .setDuration(200 )
42
+ .setInterpolator(FastOutLinearInInterpolator ())
43
+ .setListener(object : AnimatorListenerAdapter () {
44
+
45
+ override fun onAnimationEnd (animation : Animator ? ) {
46
+ buttonScaleDown.scaleX = 1f
47
+ buttonScaleDown.scaleY = 1f
48
+ }
49
+
50
+ override fun onAnimationCancel (animation : Animator ? ) {
51
+ buttonScaleDown.scaleX = 1f
52
+ buttonScaleDown.scaleY = 1f
53
+ }
54
+
55
+ })
56
+ // .withEndAction {
57
+ // buttonScaleDown.scaleX = 1f
58
+ // buttonScaleDown.scaleY = 1f
59
+ // }
60
+
61
+ }
62
+
63
+ buttonScaleUp.setOnClickListener {
64
+
65
+ val animator = buttonScaleUp.animate()
66
+ .scaleX(1.1f )
67
+ .scaleY(1.1f )
68
+ .setDuration(200 )
69
+ .setInterpolator(AccelerateDecelerateInterpolator ())
70
+ .setListener(object : AnimatorListenerAdapter () {
71
+
72
+ override fun onAnimationEnd (animation : Animator ? ) {
73
+ buttonScaleUp.scaleX = 1f
74
+ buttonScaleUp.scaleY = 1f
75
+ }
76
+
77
+ override fun onAnimationCancel (animation : Animator ? ) {
78
+ buttonScaleUp.scaleX = 1f
79
+ buttonScaleUp.scaleY = 1f
80
+ }
81
+ })
82
+ }
83
+
84
+ buttonScaleDownSpring.setOnClickListener {
85
+
86
+ buttonScaleDownSpring.scaleX = .9f
87
+ buttonScaleDownSpring.scaleY = .9f
88
+
89
+ val springForce = SpringForce ().apply {
90
+ dampingRatio = SpringForce .DAMPING_RATIO_HIGH_BOUNCY
91
+ stiffness - SpringForce .STIFFNESS_VERY_LOW
92
+ }
93
+
94
+ val animationScaleX =
95
+ SpringAnimation (buttonScaleDownSpring, DynamicAnimation .SCALE_X ).apply {
96
+ spring = springForce
97
+ }
98
+ val animationScaleY =
99
+ SpringAnimation (buttonScaleDownSpring, DynamicAnimation .SCALE_Y ).apply {
100
+ spring = springForce
101
+ }
102
+
103
+ val finalPosition = 1f
104
+ animationScaleX.animateToFinalPosition(finalPosition)
105
+ animationScaleY.animateToFinalPosition(finalPosition)
106
+ }
107
+
108
+ buttonScaleUpSpring.setOnClickListener {
109
+
110
+ buttonScaleUpSpring.scaleX = 1.1f
111
+ buttonScaleUpSpring.scaleY = 1.1f
112
+
113
+ val springForce = SpringForce ().apply {
114
+ dampingRatio = SpringForce .DAMPING_RATIO_HIGH_BOUNCY
115
+ stiffness - SpringForce .STIFFNESS_VERY_LOW
116
+ }
117
+
118
+ val animationScaleX =
119
+ SpringAnimation (buttonScaleUpSpring, DynamicAnimation .SCALE_X ).apply {
120
+ spring = springForce
121
+ }
122
+ val animationScaleY =
123
+ SpringAnimation (buttonScaleUpSpring, DynamicAnimation .SCALE_Y ).apply {
124
+ spring = springForce
125
+ }
126
+
127
+ val finalPosition = 1f
128
+ animationScaleX.animateToFinalPosition(finalPosition)
129
+ animationScaleY.animateToFinalPosition(finalPosition)
130
+ }
131
+
132
+ buttonElastic.setElasticTouchListener(scaleBy = .3f , duration = 300 )
133
+
134
+ fab.setElasticTouchListener(duration = 300 )
135
+
136
+ }
137
+ }
138
+
139
+ fun View.elasticAnimation (
140
+ grow : Boolean = false,
141
+ scaleBy : Float = 0.1f,
142
+ duration : Long = 200,
143
+ interpolator : Interpolator = LinearOutSlowInInterpolator ()
144
+ ) {
145
+
146
+ val initialScaleX = scaleX
147
+ val initialScaleY = scaleY
148
+
149
+
150
+ val viewPropertyAnimator = animate()
151
+
152
+ if (grow) {
153
+ viewPropertyAnimator.scaleX(initialScaleX + scaleBy)
154
+ viewPropertyAnimator.scaleY(initialScaleY + scaleBy)
155
+ } else {
156
+ viewPropertyAnimator.scaleX(initialScaleX - scaleBy)
157
+ viewPropertyAnimator.scaleY(initialScaleY - scaleBy)
158
+ }
159
+
160
+ viewPropertyAnimator
161
+ .setDuration(duration)
162
+ .setInterpolator(interpolator)
163
+ .setListener(object : AnimatorListenerAdapter () {
164
+
165
+ override fun onAnimationEnd (animation : Animator ? ) {
166
+ animationEnd()
167
+ }
168
+
169
+ override fun onAnimationCancel (animation : Animator ? ) {
170
+ animationEnd()
171
+ }
172
+
173
+ private fun animationEnd () {
174
+ scaleX = initialScaleX
175
+ scaleY = initialScaleY
176
+ viewPropertyAnimator.setListener(null )
177
+ }
178
+
179
+ })
180
+ }
181
+
182
+ @SuppressLint(" ClickableViewAccessibility" )
183
+ fun View.setElasticTouchListener (
184
+ grow : Boolean = false,
185
+ scaleBy : Float = 0.1f,
186
+ duration : Long = 200,
187
+ interpolator : Interpolator = LinearOutSlowInInterpolator ()
188
+ ) {
189
+ val initialScaleX = scaleX
190
+ val initialScaleY = scaleY
191
+
192
+ val scaleStartX = if (grow) {
193
+ initialScaleX + scaleBy
194
+ } else {
195
+ initialScaleX - scaleBy
196
+ }
197
+
198
+ val scaleStartY = if (grow) {
199
+ initialScaleY + scaleBy
200
+ } else {
201
+ initialScaleY - scaleBy
202
+ }
203
+
204
+ setOnTouchListener { _, event ->
205
+
206
+ var startPropertyAnimator: ViewPropertyAnimator ? = null
207
+
208
+ when (event.actionMasked) {
209
+
210
+ MotionEvent .ACTION_DOWN -> {
211
+
212
+ startPropertyAnimator = animate()
213
+
214
+ startPropertyAnimator
215
+ .setDuration(duration)
216
+ .setInterpolator(interpolator)
217
+ .scaleX(scaleStartX)
218
+ .scaleY(scaleStartY)
219
+ }
220
+
221
+ MotionEvent .ACTION_UP -> {
222
+
223
+ startPropertyAnimator?.cancel()
224
+
225
+ val viewPropertyAnimator = animate()
226
+
227
+ viewPropertyAnimator
228
+ .setDuration(duration)
229
+ .setInterpolator(interpolator)
230
+ .scaleX(initialScaleX)
231
+ .scaleY(initialScaleY)
232
+ .setListener(object : AnimatorListenerAdapter () {
233
+
234
+ override fun onAnimationEnd (animation : Animator ? ) {
235
+ animationEnd()
236
+ }
237
+
238
+ override fun onAnimationCancel (animation : Animator ? ) {
239
+ animationEnd()
240
+ }
241
+
242
+ private fun animationEnd () {
243
+ scaleX = initialScaleX
244
+ scaleY = initialScaleY
245
+ viewPropertyAnimator.setListener(null )
246
+ }
247
+ })
248
+ }
249
+ }
250
+
251
+ true
252
+ }
253
+ }
0 commit comments