1
+ package com .nineoldandroids .view .animation ;
2
+
3
+ import android .graphics .Camera ;
4
+ import android .graphics .Matrix ;
5
+ import android .graphics .RectF ;
6
+ import android .os .Build ;
7
+ import android .view .View ;
8
+ import android .view .animation .Animation ;
9
+ import android .view .animation .Transformation ;
10
+
11
+ import java .lang .ref .WeakReference ;
12
+ import java .util .WeakHashMap ;
13
+
14
+ /**
15
+ * A proxy class to allow for modifying post-3.0 view properties on all pre-3.0
16
+ * platforms. <strong>DO NOT</strong> wrap your views with this class if you
17
+ * are using {@code ObjectAnimator} as it will handle that itself.
18
+ * Source:
19
+ * http://grepcode.com/file/repo1.maven.org/maven2/com.nineoldandroids/library/2.4.0/com/nineoldandroids/view/animation/AnimatorProxy.java
20
+ */
21
+ public final class AnimatorProxy extends Animation {
22
+ /** Whether or not the current running platform needs to be proxied. */
23
+ public static final boolean NEEDS_PROXY = Integer .valueOf (Build .VERSION .SDK ).intValue () < Build .VERSION_CODES .HONEYCOMB ;
24
+
25
+ private static final WeakHashMap <View , AnimatorProxy > PROXIES =
26
+ new WeakHashMap <View , AnimatorProxy >();
27
+
28
+ /**
29
+ * Create a proxy to allow for modifying post-3.0 view properties on all
30
+ * pre-3.0 platforms. <strong>DO NOT</strong> wrap your views if you are
31
+ * using {@code ObjectAnimator} as it will handle that itself.
32
+ *
33
+ * @param view View to wrap.
34
+ * @return Proxy to post-3.0 properties.
35
+ */
36
+ public static AnimatorProxy wrap (View view ) {
37
+ AnimatorProxy proxy = PROXIES .get (view );
38
+ // This checks if the proxy already exists and whether it still is the animation of the given view
39
+ if (proxy == null || proxy != view .getAnimation ()) {
40
+ proxy = new AnimatorProxy (view );
41
+ PROXIES .put (view , proxy );
42
+ }
43
+ return proxy ;
44
+ }
45
+
46
+ private final WeakReference <View > mView ;
47
+ private final Camera mCamera = new Camera ();
48
+ private boolean mHasPivot ;
49
+
50
+ private float mAlpha = 1 ;
51
+ private float mPivotX ;
52
+ private float mPivotY ;
53
+ private float mRotationX ;
54
+ private float mRotationY ;
55
+ private float mRotationZ ;
56
+ private float mScaleX = 1 ;
57
+ private float mScaleY = 1 ;
58
+ private float mTranslationX ;
59
+ private float mTranslationY ;
60
+
61
+ private final RectF mBefore = new RectF ();
62
+ private final RectF mAfter = new RectF ();
63
+ private final Matrix mTempMatrix = new Matrix ();
64
+
65
+ private AnimatorProxy (View view ) {
66
+ setDuration (0 ); //perform transformation immediately
67
+ setFillAfter (true ); //persist transformation beyond duration
68
+ view .setAnimation (this );
69
+ mView = new WeakReference <View >(view );
70
+ }
71
+
72
+ public float getAlpha () {
73
+ return mAlpha ;
74
+ }
75
+ public void setAlpha (float alpha ) {
76
+ if (mAlpha != alpha ) {
77
+ mAlpha = alpha ;
78
+ View view = mView .get ();
79
+ if (view != null ) {
80
+ view .invalidate ();
81
+ }
82
+ }
83
+ }
84
+ public float getPivotX () {
85
+ return mPivotX ;
86
+ }
87
+ public void setPivotX (float pivotX ) {
88
+ if (!mHasPivot || mPivotX != pivotX ) {
89
+ prepareForUpdate ();
90
+ mHasPivot = true ;
91
+ mPivotX = pivotX ;
92
+ invalidateAfterUpdate ();
93
+ }
94
+ }
95
+ public float getPivotY () {
96
+ return mPivotY ;
97
+ }
98
+ public void setPivotY (float pivotY ) {
99
+ if (!mHasPivot || mPivotY != pivotY ) {
100
+ prepareForUpdate ();
101
+ mHasPivot = true ;
102
+ mPivotY = pivotY ;
103
+ invalidateAfterUpdate ();
104
+ }
105
+ }
106
+ public float getRotation () {
107
+ return mRotationZ ;
108
+ }
109
+ public void setRotation (float rotation ) {
110
+ if (mRotationZ != rotation ) {
111
+ prepareForUpdate ();
112
+ mRotationZ = rotation ;
113
+ invalidateAfterUpdate ();
114
+ }
115
+ }
116
+ public float getRotationX () {
117
+ return mRotationX ;
118
+ }
119
+ public void setRotationX (float rotationX ) {
120
+ if (mRotationX != rotationX ) {
121
+ prepareForUpdate ();
122
+ mRotationX = rotationX ;
123
+ invalidateAfterUpdate ();
124
+ }
125
+ }
126
+ public float getRotationY () {
127
+ return mRotationY ;
128
+ }
129
+
130
+ public void setRotationY (float rotationY ) {
131
+ if (mRotationY != rotationY ) {
132
+ prepareForUpdate ();
133
+ mRotationY = rotationY ;
134
+ invalidateAfterUpdate ();
135
+ }
136
+ }
137
+ public float getScaleX () {
138
+ return mScaleX ;
139
+ }
140
+ public void setScaleX (float scaleX ) {
141
+ if (mScaleX != scaleX ) {
142
+ prepareForUpdate ();
143
+ mScaleX = scaleX ;
144
+ invalidateAfterUpdate ();
145
+ }
146
+ }
147
+ public float getScaleY () {
148
+ return mScaleY ;
149
+ }
150
+ public void setScaleY (float scaleY ) {
151
+ if (mScaleY != scaleY ) {
152
+ prepareForUpdate ();
153
+ mScaleY = scaleY ;
154
+ invalidateAfterUpdate ();
155
+ }
156
+ }
157
+ public int getScrollX () {
158
+ View view = mView .get ();
159
+ if (view == null ) {
160
+ return 0 ;
161
+ }
162
+ return view .getScrollX ();
163
+ }
164
+ public void setScrollX (int value ) {
165
+ View view = mView .get ();
166
+ if (view != null ) {
167
+ view .scrollTo (value , view .getScrollY ());
168
+ }
169
+ }
170
+ public int getScrollY () {
171
+ View view = mView .get ();
172
+ if (view == null ) {
173
+ return 0 ;
174
+ }
175
+ return view .getScrollY ();
176
+ }
177
+ public void setScrollY (int value ) {
178
+ View view = mView .get ();
179
+ if (view != null ) {
180
+ view .scrollTo (view .getScrollX (), value );
181
+ }
182
+ }
183
+
184
+ public float getTranslationX () {
185
+ return mTranslationX ;
186
+ }
187
+ public void setTranslationX (float translationX ) {
188
+ if (mTranslationX != translationX ) {
189
+ prepareForUpdate ();
190
+ mTranslationX = translationX ;
191
+ invalidateAfterUpdate ();
192
+ }
193
+ }
194
+ public float getTranslationY () {
195
+ return mTranslationY ;
196
+ }
197
+ public void setTranslationY (float translationY ) {
198
+ if (mTranslationY != translationY ) {
199
+ prepareForUpdate ();
200
+ mTranslationY = translationY ;
201
+ invalidateAfterUpdate ();
202
+ }
203
+ }
204
+ public float getX () {
205
+ View view = mView .get ();
206
+ if (view == null ) {
207
+ return 0 ;
208
+ }
209
+ return view .getLeft () + mTranslationX ;
210
+ }
211
+ public void setX (float x ) {
212
+ View view = mView .get ();
213
+ if (view != null ) {
214
+ setTranslationX (x - view .getLeft ());
215
+ }
216
+ }
217
+ public float getY () {
218
+ View view = mView .get ();
219
+ if (view == null ) {
220
+ return 0 ;
221
+ }
222
+ return view .getTop () + mTranslationY ;
223
+ }
224
+ public void setY (float y ) {
225
+ View view = mView .get ();
226
+ if (view != null ) {
227
+ setTranslationY (y - view .getTop ());
228
+ }
229
+ }
230
+
231
+ private void prepareForUpdate () {
232
+ View view = mView .get ();
233
+ if (view != null ) {
234
+ computeRect (mBefore , view );
235
+ }
236
+ }
237
+ private void invalidateAfterUpdate () {
238
+ View view = mView .get ();
239
+ if (view == null || view .getParent () == null ) {
240
+ return ;
241
+ }
242
+
243
+ final RectF after = mAfter ;
244
+ computeRect (after , view );
245
+ after .union (mBefore );
246
+
247
+ ((View )view .getParent ()).invalidate (
248
+ (int ) Math .floor (after .left ),
249
+ (int ) Math .floor (after .top ),
250
+ (int ) Math .ceil (after .right ),
251
+ (int ) Math .ceil (after .bottom ));
252
+ }
253
+
254
+ private void computeRect (final RectF r , View view ) {
255
+ // compute current rectangle according to matrix transformation
256
+ final float w = view .getWidth ();
257
+ final float h = view .getHeight ();
258
+
259
+ // use a rectangle at 0,0 to make sure we don't run into issues with scaling
260
+ r .set (0 , 0 , w , h );
261
+
262
+ final Matrix m = mTempMatrix ;
263
+ m .reset ();
264
+ transformMatrix (m , view );
265
+ mTempMatrix .mapRect (r );
266
+
267
+ r .offset (view .getLeft (), view .getTop ());
268
+
269
+ // Straighten coords if rotations flipped them
270
+ if (r .right < r .left ) {
271
+ final float f = r .right ;
272
+ r .right = r .left ;
273
+ r .left = f ;
274
+ }
275
+ if (r .bottom < r .top ) {
276
+ final float f = r .top ;
277
+ r .top = r .bottom ;
278
+ r .bottom = f ;
279
+ }
280
+ }
281
+
282
+ private void transformMatrix (Matrix m , View view ) {
283
+ final float w = view .getWidth ();
284
+ final float h = view .getHeight ();
285
+ final boolean hasPivot = mHasPivot ;
286
+ final float pX = hasPivot ? mPivotX : w / 2f ;
287
+ final float pY = hasPivot ? mPivotY : h / 2f ;
288
+
289
+ final float rX = mRotationX ;
290
+ final float rY = mRotationY ;
291
+ final float rZ = mRotationZ ;
292
+ if ((rX != 0 ) || (rY != 0 ) || (rZ != 0 )) {
293
+ final Camera camera = mCamera ;
294
+ camera .save ();
295
+ camera .rotateX (rX );
296
+ camera .rotateY (rY );
297
+ camera .rotateZ (-rZ );
298
+ camera .getMatrix (m );
299
+ camera .restore ();
300
+ m .preTranslate (-pX , -pY );
301
+ m .postTranslate (pX , pY );
302
+ }
303
+
304
+ final float sX = mScaleX ;
305
+ final float sY = mScaleY ;
306
+ if ((sX != 1.0f ) || (sY != 1.0f )) {
307
+ m .postScale (sX , sY );
308
+ final float sPX = -(pX / w ) * ((sX * w ) - w );
309
+ final float sPY = -(pY / h ) * ((sY * h ) - h );
310
+ m .postTranslate (sPX , sPY );
311
+ }
312
+
313
+ m .postTranslate (mTranslationX , mTranslationY );
314
+ }
315
+
316
+ @ Override
317
+ protected void applyTransformation (float interpolatedTime , Transformation t ) {
318
+ View view = mView .get ();
319
+ if (view != null ) {
320
+ t .setAlpha (mAlpha );
321
+ transformMatrix (t .getMatrix (), view );
322
+ }
323
+ }
324
+ }
0 commit comments