1
+ package at .markushi .ui ;
2
+
3
+ import android .animation .Animator ;
4
+ import android .content .Context ;
5
+ import android .graphics .Color ;
6
+ import android .graphics .drawable .ShapeDrawable ;
7
+ import android .graphics .drawable .shapes .OvalShape ;
8
+ import android .os .Build ;
9
+ import android .util .AttributeSet ;
10
+ import android .view .View ;
11
+ import android .view .ViewGroup ;
12
+ import android .view .ViewPropertyAnimator ;
13
+
14
+ public class RevealColorView extends ViewGroup {
15
+
16
+ public static final int ANIMATION_REVEAL = 0 ;
17
+ public static final int ANIMATION_HIDE = 2 ;
18
+
19
+ private static final float SCALE = 8f ;
20
+
21
+ private View inkView ;
22
+ private int inkColor ;
23
+
24
+ private ShapeDrawable circle ;
25
+ private ViewPropertyAnimator animator ;
26
+
27
+ public RevealColorView (Context context ) {
28
+ this (context , null );
29
+ }
30
+
31
+ public RevealColorView (Context context , AttributeSet attrs ) {
32
+ this (context , attrs , 0 );
33
+ }
34
+
35
+ public RevealColorView (Context context , AttributeSet attrs , int defStyleAttr ) {
36
+ super (context , attrs , defStyleAttr );
37
+
38
+ if (isInEditMode ()) {
39
+ return ;
40
+ }
41
+
42
+ inkView = new View (context );
43
+ addView (inkView );
44
+
45
+ circle = new ShapeDrawable (new OvalShape ());
46
+
47
+ UiHelper .setBackground (inkView , circle );
48
+ inkView .setVisibility (View .INVISIBLE );
49
+ }
50
+
51
+ @ Override
52
+ protected void onLayout (boolean changed , int left , int top , int right , int bottom ) {
53
+ inkView .layout (left , top , left + inkView .getMeasuredWidth (), top + inkView .getMeasuredHeight ());
54
+ }
55
+
56
+ @ Override
57
+ protected void onMeasure (int widthMeasureSpec , int heightMeasureSpec ) {
58
+ final int width = MeasureSpec .getSize (widthMeasureSpec );
59
+ final int height = MeasureSpec .getSize (heightMeasureSpec );
60
+ setMeasuredDimension (width , height );
61
+
62
+ final float circleSize = (float ) Math .sqrt (width * width + height * height ) * 2f ;
63
+ final int size = (int ) (circleSize / SCALE );
64
+ final int sizeSpec = MeasureSpec .makeMeasureSpec (size , MeasureSpec .EXACTLY );
65
+ inkView .measure (sizeSpec , sizeSpec );
66
+ }
67
+
68
+ public void reveal (final int x , final int y , final int color , Animator .AnimatorListener listener ) {
69
+ final int duration = getResources ().getInteger (R .integer .rcv_animationDurationReveal );
70
+ reveal (x , y , color , 0 , duration , listener );
71
+ }
72
+
73
+ public void reveal (final int x , final int y , final int color , final int startRadius , long duration , final Animator .AnimatorListener listener ) {
74
+ if (color == inkColor ) {
75
+ return ;
76
+ }
77
+ inkColor = color ;
78
+
79
+ if (animator != null ) {
80
+ animator .cancel ();
81
+ }
82
+
83
+ circle .getPaint ().setColor (color );
84
+ inkView .setVisibility (View .VISIBLE );
85
+
86
+ final float startRadiusAsScale = startRadius * 2f / inkView .getHeight ();
87
+ prepareView (inkView , x , y , startRadiusAsScale );
88
+ animator = inkView .animate ().scaleX (SCALE ).scaleY (SCALE ).setDuration (duration ).setListener (new Animator .AnimatorListener () {
89
+ @ Override
90
+ public void onAnimationStart (Animator animator ) {
91
+ if (listener != null ) {
92
+ listener .onAnimationStart (animator );
93
+ }
94
+ }
95
+
96
+ @ Override
97
+ public void onAnimationEnd (Animator animation ) {
98
+ setBackgroundColor (color );
99
+ inkView .setVisibility (View .INVISIBLE );
100
+ if (listener != null ) {
101
+ listener .onAnimationEnd (animation );
102
+ }
103
+ }
104
+
105
+ @ Override
106
+ public void onAnimationCancel (Animator animator ) {
107
+ if (listener != null ) {
108
+ listener .onAnimationCancel (animator );
109
+ }
110
+ }
111
+
112
+ @ Override
113
+ public void onAnimationRepeat (Animator animator ) {
114
+ if (listener != null ) {
115
+ listener .onAnimationRepeat (animator );
116
+ }
117
+ }
118
+ });
119
+ prepareAnimator (animator , ANIMATION_REVEAL );
120
+ animator .start ();
121
+ }
122
+
123
+ public void hide (final int x , final int y , final int color , final Animator .AnimatorListener listener ) {
124
+ final int duration = getResources ().getInteger (R .integer .rcv_animationDurationHide );
125
+ hide (x , y , color , 0 , duration , listener );
126
+ }
127
+
128
+ public void hide (final int x , final int y , final int color , final int endRadius , final long duration , final Animator .AnimatorListener listener ) {
129
+ inkColor = Color .TRANSPARENT ;
130
+
131
+ if (animator != null ) {
132
+ animator .cancel ();
133
+ }
134
+
135
+ inkView .setVisibility (View .VISIBLE );
136
+ setBackgroundColor (color );
137
+
138
+ prepareView (inkView , x , y , SCALE );
139
+
140
+ final float endRadiusAsScale = endRadius * SCALE / inkView .getWidth ();
141
+ animator = inkView .animate ().scaleX (endRadiusAsScale ).scaleY (endRadiusAsScale ).setDuration (duration ).setListener (new Animator .AnimatorListener () {
142
+ @ Override
143
+ public void onAnimationStart (Animator animator ) {
144
+ if (listener != null ) {
145
+ listener .onAnimationStart (animator );
146
+ }
147
+ }
148
+
149
+ @ Override
150
+ public void onAnimationEnd (Animator animation ) {
151
+ inkView .setVisibility (View .INVISIBLE );
152
+ if (listener != null ) {
153
+ listener .onAnimationEnd (animation );
154
+ }
155
+ }
156
+
157
+ @ Override
158
+ public void onAnimationCancel (Animator animator ) {
159
+ if (listener != null ) {
160
+ listener .onAnimationCancel (animator );
161
+ }
162
+ }
163
+
164
+ @ Override
165
+ public void onAnimationRepeat (Animator animator ) {
166
+ if (listener != null ) {
167
+ listener .onAnimationRepeat (animator );
168
+ }
169
+ }
170
+ });
171
+ prepareAnimator (animator , ANIMATION_HIDE );
172
+ animator .start ();
173
+ }
174
+
175
+ public ViewPropertyAnimator prepareAnimator (ViewPropertyAnimator animator , int type ) {
176
+ if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .JELLY_BEAN ) {
177
+ animator .withLayer ();
178
+ }
179
+ return animator ;
180
+ }
181
+
182
+ private void prepareView (View view , int x , int y , float scale ) {
183
+ final int centerX = (view .getWidth () / 2 );
184
+ final int centerY = (view .getHeight () / 2 );
185
+ view .setTranslationX (x - centerX );
186
+ view .setTranslationY (y - centerY );
187
+ view .setPivotX (centerX );
188
+ view .setPivotY (centerY );
189
+ view .setScaleX (scale );
190
+ view .setScaleY (scale );
191
+ }
192
+ }
0 commit comments