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