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