• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package android.transition.cts;
17 
18 import android.animation.Animator;
19 import android.animation.AnimatorListenerAdapter;
20 import android.graphics.Matrix;
21 import android.graphics.drawable.Drawable;
22 import android.transition.ChangeImageTransform;
23 import android.transition.TransitionManager;
24 import android.transition.TransitionValues;
25 import android.util.DisplayMetrics;
26 import android.util.TypedValue;
27 import android.view.ViewGroup;
28 import android.view.ViewGroup.LayoutParams;
29 import android.widget.ImageView;
30 import android.widget.ImageView.ScaleType;
31 
32 public class ChangeImageTransformTest extends BaseTransitionTest {
33     ChangeImageTransform mChangeImageTransform;
34     Matrix mStartMatrix;
35     Matrix mEndMatrix;
36     Drawable mImage;
37     ImageView mImageView;
38 
39     @Override
setUp()40     protected void setUp() throws Exception {
41         super.setUp();
42         resetTransition();
43         mStartMatrix = null;
44         mEndMatrix = null;
45         mImage = null;
46         mImageView = null;
47     }
48 
resetTransition()49     private void resetTransition() {
50         mChangeImageTransform = new CaptureMatrix();
51         mChangeImageTransform.setDuration(100);
52         mTransition = mChangeImageTransform;
53         resetListener();
54     }
55 
testCenterToFitXY()56     public void testCenterToFitXY() throws Throwable {
57         transformImage(ScaleType.CENTER, ScaleType.FIT_XY);
58         assertMatrixMatches(centerMatrix(), mStartMatrix);
59         assertMatrixMatches(fitXYMatrix(), mEndMatrix);
60     }
61 
testCenterCropToFitCenter()62     public void testCenterCropToFitCenter() throws Throwable {
63         transformImage(ScaleType.CENTER_CROP, ScaleType.FIT_CENTER);
64         assertMatrixMatches(centerCropMatrix(), mStartMatrix);
65         assertMatrixMatches(fitCenterMatrix(), mEndMatrix);
66     }
67 
testCenterInsideToFitEnd()68     public void testCenterInsideToFitEnd() throws Throwable {
69         transformImage(ScaleType.CENTER_INSIDE, ScaleType.FIT_END);
70         // CENTER_INSIDE and CENTER are the same when the image is smaller than the View
71         assertMatrixMatches(centerMatrix(), mStartMatrix);
72         assertMatrixMatches(fitEndMatrix(), mEndMatrix);
73     }
74 
testFitStartToCenter()75     public void testFitStartToCenter() throws Throwable {
76         transformImage(ScaleType.FIT_START, ScaleType.CENTER);
77         assertMatrixMatches(fitStartMatrix(), mStartMatrix);
78         assertMatrixMatches(centerMatrix(), mEndMatrix);
79     }
80 
centerMatrix()81     private Matrix centerMatrix() {
82         int imageWidth = mImage.getIntrinsicWidth();
83         int imageViewWidth = mImageView.getWidth();
84         float tx = Math.round((imageViewWidth - imageWidth)/2f);
85 
86         int imageHeight = mImage.getIntrinsicHeight();
87         int imageViewHeight = mImageView.getHeight();
88         float ty = Math.round((imageViewHeight - imageHeight)/2f);
89 
90         Matrix matrix = new Matrix();
91         matrix.postTranslate(tx, ty);
92         return matrix;
93     }
94 
fitXYMatrix()95     private Matrix fitXYMatrix() {
96         int imageWidth = mImage.getIntrinsicWidth();
97         int imageViewWidth = mImageView.getWidth();
98         float scaleX = ((float)imageViewWidth)/imageWidth;
99 
100         int imageHeight = mImage.getIntrinsicHeight();
101         int imageViewHeight = mImageView.getHeight();
102         float scaleY = ((float)imageViewHeight)/imageHeight;
103 
104         Matrix matrix = new Matrix();
105         matrix.postScale(scaleX, scaleY);
106         return matrix;
107     }
108 
centerCropMatrix()109     private Matrix centerCropMatrix() {
110         int imageWidth = mImage.getIntrinsicWidth();
111         int imageViewWidth = mImageView.getWidth();
112         float scaleX = ((float)imageViewWidth)/imageWidth;
113 
114         int imageHeight = mImage.getIntrinsicHeight();
115         int imageViewHeight = mImageView.getHeight();
116         float scaleY = ((float)imageViewHeight)/imageHeight;
117 
118         float maxScale = Math.max(scaleX, scaleY);
119 
120         float width = imageWidth * maxScale;
121         float height = imageHeight * maxScale;
122         float tx = Math.round((imageViewWidth - width) / 2f);
123         float ty = Math.round((imageViewHeight - height) / 2f);
124 
125         Matrix matrix = new Matrix();
126         matrix.postScale(maxScale, maxScale);
127         matrix.postTranslate(tx, ty);
128         return matrix;
129     }
130 
fitCenterMatrix()131     private Matrix fitCenterMatrix() {
132         int imageWidth = mImage.getIntrinsicWidth();
133         int imageViewWidth = mImageView.getWidth();
134         float scaleX = ((float)imageViewWidth)/imageWidth;
135 
136         int imageHeight = mImage.getIntrinsicHeight();
137         int imageViewHeight = mImageView.getHeight();
138         float scaleY = ((float)imageViewHeight)/imageHeight;
139 
140         float minScale = Math.min(scaleX, scaleY);
141 
142         float width = imageWidth * minScale;
143         float height = imageHeight * minScale;
144         float tx = (imageViewWidth - width) / 2f;
145         float ty = (imageViewHeight - height) / 2f;
146 
147         Matrix matrix = new Matrix();
148         matrix.postScale(minScale, minScale);
149         matrix.postTranslate(tx, ty);
150         return matrix;
151     }
152 
fitStartMatrix()153     private Matrix fitStartMatrix() {
154         int imageWidth = mImage.getIntrinsicWidth();
155         int imageViewWidth = mImageView.getWidth();
156         float scaleX = ((float)imageViewWidth)/imageWidth;
157 
158         int imageHeight = mImage.getIntrinsicHeight();
159         int imageViewHeight = mImageView.getHeight();
160         float scaleY = ((float)imageViewHeight)/imageHeight;
161 
162         float minScale = Math.min(scaleX, scaleY);
163 
164         Matrix matrix = new Matrix();
165         matrix.postScale(minScale, minScale);
166         return matrix;
167     }
168 
fitEndMatrix()169     private Matrix fitEndMatrix() {
170         int imageWidth = mImage.getIntrinsicWidth();
171         int imageViewWidth = mImageView.getWidth();
172         float scaleX = ((float)imageViewWidth)/imageWidth;
173 
174         int imageHeight = mImage.getIntrinsicHeight();
175         int imageViewHeight = mImageView.getHeight();
176         float scaleY = ((float)imageViewHeight)/imageHeight;
177 
178         float minScale = Math.min(scaleX, scaleY);
179 
180         float width = imageWidth * minScale;
181         float height = imageHeight * minScale;
182         float tx = imageViewWidth - width;
183         float ty = imageViewHeight - height;
184 
185         Matrix matrix = new Matrix();
186         matrix.postScale(minScale, minScale);
187         matrix.postTranslate(tx, ty);
188         return matrix;
189     }
190 
assertMatrixMatches(Matrix expected, Matrix matrix)191     private void assertMatrixMatches(Matrix expected, Matrix matrix) {
192         if (expected == null) {
193             assertNull(matrix);
194             return;
195         }
196         assertNotNull(matrix);
197         float[] expectedValues = new float[9];
198         expected.getValues(expectedValues);
199 
200         float[] values = new float[9];
201         matrix.getValues(values);
202 
203         for (int i = 0; i < values.length; i++) {
204             final float expectedValue = expectedValues[i];
205             final float value = values[i];
206             assertEquals("Value [" + i + "]", expectedValue, value, 0.01f);
207         }
208     }
209 
transformImage(ScaleType startScale, final ScaleType endScale)210     private void transformImage(ScaleType startScale, final ScaleType endScale) throws Throwable {
211         final ImageView imageView = enterImageViewScene(startScale);
212         runTestOnUiThread(new Runnable() {
213             @Override
214             public void run() {
215                 TransitionManager.beginDelayedTransition(mSceneRoot, mChangeImageTransform);
216                 imageView.setScaleType(endScale);
217             }
218         });
219         waitForStart();
220         int expectedEndCount = (startScale == endScale) ? 0 : 1;
221         assertEquals(expectedEndCount, mListener.endLatch.getCount());
222         waitForEnd(200);
223     }
224 
enterImageViewScene(final ScaleType scaleType)225     private ImageView enterImageViewScene(final ScaleType scaleType) throws Throwable {
226         enterScene(R.layout.scene4);
227         final ViewGroup container = (ViewGroup) mActivity.findViewById(R.id.holder);
228         final ImageView[] imageViews = new ImageView[1];
229         runTestOnUiThread(new Runnable() {
230             @Override
231             public void run() {
232                 mImageView = new ImageView(mActivity);
233                 mImage = mActivity.getDrawable(android.R.drawable.ic_media_play);
234                 mImageView.setImageDrawable(mImage);
235                 mImageView.setScaleType(scaleType);
236                 imageViews[0] = mImageView;
237                 container.addView(mImageView);
238                 LayoutParams layoutParams = mImageView.getLayoutParams();
239                 DisplayMetrics metrics = mActivity.getResources().getDisplayMetrics();
240                 float size = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 50, metrics);
241                 layoutParams.width = Math.round(size);
242                 layoutParams.height = Math.round(size * 2);
243                 mImageView.setLayoutParams(layoutParams);
244             }
245         });
246         getInstrumentation().waitForIdleSync();
247         return imageViews[0];
248     }
249 
250     private class CaptureMatrix extends ChangeImageTransform {
251         @Override
createAnimator(ViewGroup sceneRoot, TransitionValues startValues, TransitionValues endValues)252         public Animator createAnimator(ViewGroup sceneRoot, TransitionValues startValues,
253                 TransitionValues endValues) {
254             Animator animator = super.createAnimator(sceneRoot, startValues, endValues);
255             animator.addListener(new CaptureMatrixListener((ImageView) endValues.view));
256             return animator;
257         }
258     }
259 
260     private class CaptureMatrixListener extends AnimatorListenerAdapter {
261         private final ImageView mImageView;
262 
CaptureMatrixListener(ImageView view)263         public CaptureMatrixListener(ImageView view) {
264             mImageView = view;
265         }
266 
267         @Override
onAnimationStart(Animator animation)268         public void onAnimationStart(Animator animation) {
269             mStartMatrix = copyMatrix();
270         }
271 
272         @Override
onAnimationEnd(Animator animation)273         public void onAnimationEnd(Animator animation) {
274             mEndMatrix = copyMatrix();
275         }
276 
copyMatrix()277         private Matrix copyMatrix() {
278             Matrix matrix = mImageView.getImageMatrix();
279             if (matrix != null) {
280                 matrix = new Matrix(matrix);
281             }
282             return matrix;
283         }
284     }
285 }
286 
287