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