• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2012 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.animation.cts;
17 
18 import static org.junit.Assert.assertEquals;
19 import static org.junit.Assert.assertFalse;
20 import static org.junit.Assert.assertNull;
21 import static org.junit.Assert.assertTrue;
22 
23 import android.animation.Animator;
24 import android.animation.LayoutTransition;
25 import android.animation.LayoutTransition.TransitionListener;
26 import android.animation.ObjectAnimator;
27 import android.animation.PropertyValuesHolder;
28 import android.animation.TimeInterpolator;
29 import android.animation.ValueAnimator;
30 import android.os.SystemClock;
31 import android.view.View;
32 import android.view.ViewGroup;
33 import android.view.animation.AccelerateInterpolator;
34 import android.widget.Button;
35 import android.widget.LinearLayout;
36 
37 import androidx.test.InstrumentationRegistry;
38 import androidx.test.filters.MediumTest;
39 import androidx.test.rule.ActivityTestRule;
40 import androidx.test.runner.AndroidJUnit4;
41 
42 import com.android.compatibility.common.util.AdoptShellPermissionsRule;
43 
44 import org.junit.After;
45 import org.junit.Before;
46 import org.junit.Rule;
47 import org.junit.Test;
48 import org.junit.runner.RunWith;
49 
50 import java.util.Iterator;
51 import java.util.LinkedList;
52 import java.util.List;
53 import java.util.concurrent.CountDownLatch;
54 import java.util.concurrent.TimeUnit;
55 
56 @MediumTest
57 @RunWith(AndroidJUnit4.class)
58 public class LayoutAnimationTest {
59     private LayoutAnimationActivity mActivity;
60     private LayoutTransition mLayoutTransition;
61     private LinearLayout mView;
62     private Button mButton;
63     private float mOldAnimationScale = 1f;
64 
65     @Rule(order = 0)
66     public AdoptShellPermissionsRule mAdoptShellPermissionsRule =
67             new AdoptShellPermissionsRule(
68                     androidx.test.platform.app.InstrumentationRegistry
69                             .getInstrumentation().getUiAutomation(),
70                     android.Manifest.permission.START_ACTIVITIES_FROM_SDK_SANDBOX);
71 
72     @Rule(order = 1)
73     public ActivityTestRule<LayoutAnimationActivity> mActivityRule =
74             new ActivityTestRule<>(LayoutAnimationActivity.class);
75 
76     @Before
setup()77     public void setup() {
78         mOldAnimationScale = ValueAnimator.getDurationScale();
79         ValueAnimator.setDurationScale(1f);
80         InstrumentationRegistry.getInstrumentation().setInTouchMode(true);
81         mActivity = mActivityRule.getActivity();
82         mView = (LinearLayout) mActivity.findViewById(R.id.container);
83         mButton = (Button)mActivity.findViewById(R.id.button1);
84         mLayoutTransition = new LayoutTransition();
85     }
86 
87     @After
teardown()88     public void teardown() {
89         ValueAnimator.setDurationScale(mOldAnimationScale);
90     }
91 
92     @Test
testAddTransitionListener()93     public void testAddTransitionListener() throws Throwable {
94         MyTransitionListener listener = new MyTransitionListener();
95         assertNull(mLayoutTransition.getTransitionListeners());
96         mLayoutTransition.addTransitionListener(listener);
97 
98         List<TransitionListener> layoutTransitionList = mLayoutTransition.getTransitionListeners();
99         TransitionListener actualListener = layoutTransitionList.get(0);
100         assertEquals(1, layoutTransitionList.size());
101         assertEquals(listener, actualListener);
102     }
103 
104     @Test
testIsRunning()105     public void testIsRunning() throws Throwable {
106         setDefaultTransition();
107         assertFalse(mLayoutTransition.isRunning());
108         clickButton();
109         assertTrue(mLayoutTransition.isRunning());
110     }
111 
112     @Test
testIsChangingLayout()113     public void testIsChangingLayout() throws Throwable {
114         long duration = 5000L;
115         mView.setLayoutTransition(mLayoutTransition);
116         mLayoutTransition.setDuration(duration);
117         mLayoutTransition.setInterpolator(LayoutTransition.CHANGE_APPEARING,
118                 new AccelerateInterpolator());
119 
120         assertFalse(mLayoutTransition.isChangingLayout());
121         clickButton();
122         assertTrue(mLayoutTransition.isChangingLayout());
123     }
124 
125     @Test
testSetDuration()126     public void testSetDuration() {
127         long duration = 1000l;
128         mLayoutTransition.setDuration(duration);
129 
130         assertEquals(duration, mLayoutTransition.getDuration(LayoutTransition.APPEARING));
131         assertEquals(duration, mLayoutTransition.getDuration(LayoutTransition.CHANGE_APPEARING));
132         assertEquals(duration,
133                      mLayoutTransition.getDuration(LayoutTransition.CHANGE_DISAPPEARING));
134         assertEquals(duration, mLayoutTransition.getDuration(LayoutTransition.DISAPPEARING));
135     }
136 
137     @Test
testSetDurationForTransitionType()138     public void testSetDurationForTransitionType() {
139         long duration = 1000l;
140         mLayoutTransition.setDuration(LayoutTransition.APPEARING, duration);
141         assertEquals(duration, mLayoutTransition.getDuration(LayoutTransition.APPEARING));
142     }
143 
144     @Test
testSetInterpolator()145     public void testSetInterpolator() {
146         TimeInterpolator interpolator = new AccelerateInterpolator();
147         mLayoutTransition.setInterpolator(LayoutTransition.APPEARING, interpolator);
148         assertEquals(interpolator, mLayoutTransition.getInterpolator(
149                 LayoutTransition.APPEARING));
150     }
151 
152     @Test
testSetAnimator()153     public void testSetAnimator() {
154         float startAlpha = 0.0f;
155         float endAlpha = 0.5f;
156         PropertyValuesHolder pvhAlpha = PropertyValuesHolder.ofFloat("alpha", startAlpha,
157                 endAlpha);
158         ObjectAnimator appearingAnimator = ObjectAnimator.ofPropertyValuesHolder(
159                 (Object) null, pvhAlpha);
160         appearingAnimator.setInterpolator(new AccelerateInterpolator());
161         mLayoutTransition.setAnimator(LayoutTransition.APPEARING, appearingAnimator);
162         assertEquals(appearingAnimator, mLayoutTransition.getAnimator(LayoutTransition.APPEARING));
163     }
164 
165     @Test
testAnimationWithAnimator()166     public void testAnimationWithAnimator() throws Throwable {
167         MyTransitionListener listener = new MyTransitionListener();
168         mLayoutTransition.addTransitionListener(listener);
169         mLayoutTransition.setAnimateParentHierarchy(false);
170         long duration = 2000;
171         mView.setLayoutTransition(mLayoutTransition);
172         mLayoutTransition.setDuration(duration);
173         float startAlpha = 0.0f;
174         float endAlpha = 0.5f;
175         PropertyValuesHolder pvhAlpha = PropertyValuesHolder.ofFloat("alpha", startAlpha,
176                 endAlpha);
177         ObjectAnimator appearingAnimator = ObjectAnimator.ofPropertyValuesHolder(
178                 (Object) null, pvhAlpha);
179         appearingAnimator.setInterpolator(new AccelerateInterpolator());
180 
181         mLayoutTransition.setAnimator(LayoutTransition.APPEARING, appearingAnimator);
182 
183         List<Float> alphaList = new LinkedList<>();
184         clickButton();
185         while (listener.mTransition) {
186             float alpha = mActivity.getLastButton().getAlpha();
187             alphaList.add(alpha);
188             SystemClock.sleep(200);
189         }
190         Iterator<Float> iterator = alphaList.iterator();
191         float lastValue = 0.0f;
192         while(iterator.hasNext()){
193             float alphaValue = iterator.next();
194             assertTrue(alphaValue >= lastValue);
195             assertTrue(alphaValue >= startAlpha);
196             assertTrue(alphaValue <= endAlpha);
197             lastValue = alphaValue;
198         }
199     }
200 
201     @Test
testStartDelay()202     public void testStartDelay() {
203         long delay = 100l;
204         int transitionType = LayoutTransition.APPEARING;
205         mLayoutTransition.setStartDelay(transitionType, delay);
206         assertEquals(delay, mLayoutTransition.getStartDelay(transitionType));
207     }
208 
209     @Test
testSetStagger()210     public void testSetStagger() {
211         long duration = 100;
212         int transitionType = LayoutTransition.CHANGE_APPEARING;
213         mLayoutTransition.setStagger(transitionType, duration);
214         assertEquals(duration, mLayoutTransition.getStagger(transitionType));
215     }
216 
setDefaultTransition()217     private void setDefaultTransition() {
218         long duration = 5000;
219         mView.setLayoutTransition(mLayoutTransition);
220         mLayoutTransition.setDuration(duration);
221         mLayoutTransition.setInterpolator(LayoutTransition.APPEARING,
222                 new AccelerateInterpolator());
223     }
224 
clickButton()225     private void clickButton() throws Throwable {
226         CountDownLatch startLatch = new CountDownLatch(1);
227         TransitionListener listener = new TransitionListener() {
228 
229             @Override
230             public void startTransition(
231                     LayoutTransition layoutTransition,
232                     ViewGroup viewGroup,
233                     View view,
234                     int i
235             ) {
236                 startLatch.countDown();
237             }
238 
239             @Override
240             public void endTransition(
241                     LayoutTransition layoutTransition,
242                     ViewGroup viewGroup,
243                     View view,
244                     int i
245             ) {
246             }
247         };
248         mLayoutTransition.addTransitionListener(listener);
249         mActivityRule.runOnUiThread(mButton::callOnClick);
250         InstrumentationRegistry.getInstrumentation().waitForIdleSync();
251         assertTrue(startLatch.await(5, TimeUnit.SECONDS));
252     }
253 
254     class MyTransitionListener implements LayoutTransition.TransitionListener {
255         ViewGroup mContainer;
256         View mView;
257         int mTransitionType;
258         boolean mTransition = false;
endTransition(LayoutTransition transition, ViewGroup container, View view, int transitionType)259         public void endTransition(LayoutTransition transition,
260                 ViewGroup container, View view, int transitionType) {
261             this.mContainer = container;
262             this.mView = view;
263             this.mTransitionType = transitionType;
264             mTransition = false;
265         }
266 
startTransition(LayoutTransition transition, ViewGroup container, View view, int transitionType)267         public void startTransition(LayoutTransition transition,
268                 ViewGroup container, View view, int transitionType) {
269             this.mContainer = container;
270             this.mView = view;
271             this.mTransitionType = transitionType;
272             mTransition = true;
273         }
274     }
275 
276     class MyLayoutTransition extends LayoutTransition {
277         boolean mAddChild = false;
278         boolean mHideChild = false;
279         boolean mRemoveChild = false;
280         boolean mShowChild = false;
281         boolean mSetAnimator = false;
282         boolean mRemoveListener = false;
283         boolean isChangingLayout = false;
284 
285         @Override
addChild(ViewGroup parent, View child)286         public void addChild(ViewGroup parent, View child) {
287             super.addChild(parent, child);
288             mAddChild = true;
289         }
290 
291         @Override
hideChild(ViewGroup parent, View child)292         public void hideChild(ViewGroup parent, View child) {
293             super.hideChild(parent, child);
294             mHideChild = true;
295         }
296 
297         @Override
isChangingLayout()298         public boolean isChangingLayout() {
299             return super.isChangingLayout();
300         }
301 
302         @Override
isRunning()303         public boolean isRunning() {
304             isChangingLayout =  true;
305             return super.isRunning();
306         }
307 
308         @Override
removeChild(ViewGroup parent, View child)309         public void removeChild(ViewGroup parent, View child) {
310             super.removeChild(parent, child);
311             mRemoveChild = true;
312         }
313 
314         @Override
removeTransitionListener(TransitionListener listener)315         public void removeTransitionListener(TransitionListener listener) {
316             super.removeTransitionListener(listener);
317             mRemoveListener = true;
318         }
319 
320         @Override
setAnimator(int transitionType, Animator animator)321         public void setAnimator(int transitionType, Animator animator) {
322             super.setAnimator(transitionType, animator);
323             mSetAnimator = true;
324         }
325 
326         @Override
showChild(ViewGroup parent, View child)327         public void showChild(ViewGroup parent, View child) {
328             super.showChild(parent, child);
329             mShowChild = true;
330         }
331     }
332 }
333 
334