mobile/android/base/animation/AnimatorProxy.java

branch
TOR_BUG_3246
changeset 4
fc2d59ddac77
equal deleted inserted replaced
-1:000000000000 0:78faa7514641
1 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
4 * You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6 package org.mozilla.gecko.animation;
7
8 import android.graphics.Matrix;
9 import android.graphics.RectF;
10 import android.os.Build;
11 import android.view.View;
12 import android.view.ViewGroup;
13 import android.view.animation.Animation;
14 import android.view.animation.AnimationUtils;
15 import android.view.animation.Transformation;
16
17 import java.lang.ref.WeakReference;
18 import java.util.WeakHashMap;
19
20 class AnimatorProxy {
21 private static final WeakHashMap<View, AnimatorProxy> PROXIES =
22 new WeakHashMap<View, AnimatorProxy>();
23
24 private static interface AnimatorProxyImpl {
25 public float getAlpha();
26 public void setAlpha(float alpha);
27
28 public float getTranslationX();
29 public void setTranslationX(float translationX);
30
31 public float getTranslationY();
32 public void setTranslationY(float translationY);
33
34 public View getView();
35 }
36
37 private AnimatorProxyImpl mImpl;
38
39 private AnimatorProxy(AnimatorProxyImpl impl) {
40 mImpl = impl;
41 }
42
43 public static AnimatorProxy create(View view) {
44 AnimatorProxy proxy = PROXIES.get(view);
45 boolean needsAnimationProxy = (Build.VERSION.SDK_INT < 11);
46
47 // If the view's animation proxy has been overridden from somewhere else, we need to
48 // create a new AnimatorProxy for the view.
49 if (proxy == null || (needsAnimationProxy && proxy.mImpl != view.getAnimation())) {
50 AnimatorProxyImpl impl = (needsAnimationProxy ? new AnimatorProxyPreHC(view) :
51 new AnimatorProxyPostHC(view));
52
53 proxy = new AnimatorProxy(impl);
54 PROXIES.put(view, proxy);
55 }
56
57 return proxy;
58 }
59
60 public int getWidth() {
61 View view = mImpl.getView();
62 if (view != null)
63 return view.getWidth();
64
65 return 0;
66 }
67
68 public void setWidth(int width) {
69 View view = mImpl.getView();
70 if (view != null) {
71 ViewGroup.LayoutParams lp = view.getLayoutParams();
72 lp.width = width;
73 view.setLayoutParams(lp);
74 }
75 }
76
77 public int getHeight() {
78 View view = mImpl.getView();
79 if (view != null)
80 return view.getHeight();
81
82 return 0;
83 }
84
85 public void setHeight(int height) {
86 View view = mImpl.getView();
87 if (view != null) {
88 ViewGroup.LayoutParams lp = view.getLayoutParams();
89 lp.height = height;
90 view.setLayoutParams(lp);
91 }
92 }
93
94 public int getScrollX() {
95 View view = mImpl.getView();
96 if (view != null)
97 return view.getScrollX();
98
99 return 0;
100 }
101
102 public int getScrollY() {
103 View view = mImpl.getView();
104 if (view != null)
105 return view.getScrollY();
106
107 return 0;
108 }
109
110 public void scrollTo(int scrollX, int scrollY) {
111 View view = mImpl.getView();
112 if (view != null)
113 view.scrollTo(scrollX, scrollY);
114 }
115
116 public float getAlpha() {
117 return mImpl.getAlpha();
118 }
119
120 public void setAlpha(float alpha) {
121 mImpl.setAlpha(alpha);
122 }
123
124 public float getTranslationX() {
125 return mImpl.getTranslationX();
126 }
127
128 public void setTranslationX(float translationX) {
129 mImpl.setTranslationX(translationX);
130 }
131
132 public float getTranslationY() {
133 return mImpl.getTranslationY();
134 }
135
136 public void setTranslationY(float translationY) {
137 mImpl.setTranslationY(translationY);
138 }
139
140 /*
141 * AnimatorProxyPreHC uses the technique used by the NineOldAndroids described here:
142 * http://jakewharton.com/advanced-pre-honeycomb-animation/
143 *
144 * Some of this code is based on Jake Wharton's AnimatorProxy released as part of
145 * the NineOldAndroids library under the Apache License 2.0.
146 */
147 private static class AnimatorProxyPreHC extends Animation implements AnimatorProxyImpl {
148 private WeakReference<View> mViewRef;
149
150 private final RectF mBefore;
151 private final RectF mAfter;
152 private final Matrix mTempMatrix;
153
154 private float mAlpha;
155 private float mTranslationX;
156 private float mTranslationY;
157
158 public AnimatorProxyPreHC(View view) {
159 mBefore = new RectF();
160 mAfter = new RectF();
161 mTempMatrix = new Matrix();
162
163 mAlpha = 1;
164 mTranslationX = 0;
165 mTranslationY = 0;
166
167 loadCurrentTransformation(view);
168
169 setDuration(0);
170 setFillAfter(true);
171 view.setAnimation(this);
172
173 mViewRef = new WeakReference<View>(view);
174 }
175
176 private void loadCurrentTransformation(View view) {
177 Animation animation = view.getAnimation();
178 if (animation == null)
179 return;
180
181 Transformation transformation = new Transformation();
182 float[] matrix = new float[9];
183
184 animation.getTransformation(AnimationUtils.currentAnimationTimeMillis(), transformation);
185 transformation.getMatrix().getValues(matrix);
186
187 mAlpha = transformation.getAlpha();
188 mTranslationX = matrix[Matrix.MTRANS_X];
189 mTranslationY = matrix[Matrix.MTRANS_Y];
190 }
191
192 private void prepareForUpdate() {
193 View view = mViewRef.get();
194 if (view != null)
195 computeRect(mBefore, view);
196 }
197
198 private void computeRect(final RectF r, View view) {
199 final float w = view.getWidth();
200 final float h = view.getHeight();
201
202 r.set(0, 0, w, h);
203
204 final Matrix m = mTempMatrix;
205 m.reset();
206 transformMatrix(m, view);
207 mTempMatrix.mapRect(r);
208
209 r.offset(view.getLeft(), view.getTop());
210 }
211
212 private void transformMatrix(Matrix m, View view) {
213 m.postTranslate(mTranslationX, mTranslationY);
214 }
215
216 private void invalidateAfterUpdate() {
217 View view = mViewRef.get();
218 if (view == null || view.getParent() == null)
219 return;
220
221 final RectF after = mAfter;
222 computeRect(after, view);
223 after.union(mBefore);
224
225 ((View)view.getParent()).invalidate(
226 (int) Math.floor(after.left),
227 (int) Math.floor(after.top),
228 (int) Math.ceil(after.right),
229 (int) Math.ceil(after.bottom));
230 }
231
232 @Override
233 public float getAlpha() {
234 return mAlpha;
235 }
236
237 @Override
238 public void setAlpha(float alpha) {
239 if (mAlpha == alpha)
240 return;
241
242 mAlpha = alpha;
243
244 View view = mViewRef.get();
245 if (view != null)
246 view.invalidate();
247 }
248
249 @Override
250 public float getTranslationX() {
251 return mTranslationX;
252 }
253
254 @Override
255 public void setTranslationX(float translationX) {
256 if (mTranslationX == translationX)
257 return;
258
259 prepareForUpdate();
260 mTranslationX = translationX;
261 invalidateAfterUpdate();
262 }
263
264 @Override
265 public float getTranslationY() {
266 return mTranslationY;
267 }
268
269 @Override
270 public void setTranslationY(float translationY) {
271 if (mTranslationY == translationY)
272 return;
273
274 prepareForUpdate();
275 mTranslationY = translationY;
276 invalidateAfterUpdate();
277 }
278
279 @Override
280 public View getView() {
281 return mViewRef.get();
282 }
283
284 @Override
285 protected void applyTransformation(float interpolatedTime, Transformation t) {
286 View view = mViewRef.get();
287 if (view != null) {
288 t.setAlpha(mAlpha);
289 transformMatrix(t.getMatrix(), view);
290 }
291 }
292 }
293
294 private static class AnimatorProxyPostHC implements AnimatorProxyImpl {
295 private WeakReference<View> mViewRef;
296
297 public AnimatorProxyPostHC(View view) {
298 mViewRef = new WeakReference<View>(view);
299 }
300
301 @Override
302 public float getAlpha() {
303 View view = mViewRef.get();
304 if (view != null)
305 return view.getAlpha();
306
307 return 1;
308 }
309
310 @Override
311 public void setAlpha(float alpha) {
312 View view = mViewRef.get();
313 if (view != null)
314 view.setAlpha(alpha);
315 }
316
317 @Override
318 public float getTranslationX() {
319 View view = mViewRef.get();
320 if (view != null)
321 return view.getTranslationX();
322
323 return 0;
324 }
325
326 @Override
327 public void setTranslationX(float translationX) {
328 View view = mViewRef.get();
329 if (view != null)
330 view.setTranslationX(translationX);
331 }
332
333 @Override
334 public float getTranslationY() {
335 View view = mViewRef.get();
336 if (view != null)
337 return view.getTranslationY();
338
339 return 0;
340 }
341
342 @Override
343 public void setTranslationY(float translationY) {
344 View view = mViewRef.get();
345 if (view != null)
346 view.setTranslationY(translationY);
347 }
348
349 @Override
350 public View getView() {
351 return mViewRef.get();
352 }
353 }
354 }
355

mercurial