• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 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.support.v4.app.test;
17 
18 import android.app.Activity;
19 import android.content.Context;
20 import android.content.Intent;
21 import android.os.Build.VERSION;
22 import android.os.Build.VERSION_CODES;
23 import android.os.Bundle;
24 import android.support.fragment.test.R;
25 import android.support.v4.app.Fragment;
26 import android.support.v4.app.FragmentActivity;
27 import android.transition.Transition;
28 import android.transition.Transition.TransitionListener;
29 import android.transition.TransitionInflater;
30 import android.view.LayoutInflater;
31 import android.view.View;
32 import android.view.ViewGroup;
33 
34 import java.util.concurrent.CountDownLatch;
35 import java.util.concurrent.TimeUnit;
36 
37 /**
38  * A simple activity used for Fragment Transitions and lifecycle event ordering
39  */
40 public class FragmentTestActivity extends FragmentActivity {
41     @Override
onCreate(Bundle icicle)42     public void onCreate(Bundle icicle) {
43         super.onCreate(icicle);
44         setContentView(R.layout.activity_content);
45     }
46 
47     public static class TestFragment extends Fragment {
48         public static final int ENTER = 0;
49         public static final int RETURN = 1;
50         public static final int EXIT = 2;
51         public static final int REENTER = 3;
52         public static final int SHARED_ELEMENT_ENTER = 4;
53         public static final int SHARED_ELEMENT_RETURN = 5;
54         private static final int TRANSITION_COUNT = 6;
55 
56         private static final String LAYOUT_ID = "layoutId";
57         private static final String TRANSITION_KEY = "transition_";
58         private int mLayoutId = R.layout.fragment_start;
59         private final int[] mTransitionIds = new int[] {
60                 R.transition.fade,
61                 R.transition.fade,
62                 R.transition.fade,
63                 R.transition.fade,
64                 R.transition.change_bounds,
65                 R.transition.change_bounds,
66         };
67         private final Object[] mListeners = new Object[TRANSITION_COUNT];
68 
TestFragment()69         public TestFragment() {
70             if (VERSION.SDK_INT >= VERSION_CODES.KITKAT) {
71                 for (int i = 0; i < TRANSITION_COUNT; i++) {
72                     mListeners[i] = new TransitionCalledListener();
73                 }
74             }
75         }
76 
create(int layoutId)77         public static TestFragment create(int layoutId) {
78             TestFragment testFragment = new TestFragment();
79             testFragment.mLayoutId = layoutId;
80             return testFragment;
81         }
82 
clearTransitions()83         public void clearTransitions() {
84             for (int i = 0; i < TRANSITION_COUNT; i++) {
85                 mTransitionIds[i] = 0;
86             }
87         }
88 
clearNotifications()89         public void clearNotifications() {
90             for (int i = 0; i < TRANSITION_COUNT; i++) {
91                 ((TransitionCalledListener)mListeners[i]).startLatch = new CountDownLatch(1);
92                 ((TransitionCalledListener)mListeners[i]).endLatch = new CountDownLatch(1);
93             }
94         }
95 
96         @Override
onCreate(Bundle savedInstanceState)97         public void onCreate(Bundle savedInstanceState) {
98             super.onCreate(savedInstanceState);
99             if (savedInstanceState != null) {
100                 mLayoutId = savedInstanceState.getInt(LAYOUT_ID, mLayoutId);
101                 for (int i = 0; i < TRANSITION_COUNT; i++) {
102                     String key = TRANSITION_KEY + i;
103                     mTransitionIds[i] = savedInstanceState.getInt(key, mTransitionIds[i]);
104                 }
105             }
106         }
107 
108         @Override
onSaveInstanceState(Bundle outState)109         public void onSaveInstanceState(Bundle outState) {
110             super.onSaveInstanceState(outState);
111             outState.putInt(LAYOUT_ID, mLayoutId);
112             for (int i = 0; i < TRANSITION_COUNT; i++) {
113                 String key = TRANSITION_KEY + i;
114                 outState.putInt(key, mTransitionIds[i]);
115             }
116         }
117 
118         @Override
onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)119         public View onCreateView(LayoutInflater inflater, ViewGroup container,
120                 Bundle savedInstanceState) {
121             return inflater.inflate(mLayoutId, container, false);
122         }
123 
124         @SuppressWarnings("deprecation")
125         @Override
onAttach(Activity activity)126         public void onAttach(Activity activity) {
127             super.onAttach(activity);
128             if (VERSION.SDK_INT > VERSION_CODES.KITKAT) {
129                 setEnterTransition(loadTransition(ENTER));
130                 setReenterTransition(loadTransition(REENTER));
131                 setExitTransition(loadTransition(EXIT));
132                 setReturnTransition(loadTransition(RETURN));
133                 setSharedElementEnterTransition(loadTransition(SHARED_ELEMENT_ENTER));
134                 setSharedElementReturnTransition(loadTransition(SHARED_ELEMENT_RETURN));
135             }
136         }
137 
wasStartCalled(int transitionKey)138         public boolean wasStartCalled(int transitionKey) {
139             return ((TransitionCalledListener)mListeners[transitionKey]).startLatch.getCount() == 0;
140         }
141 
wasEndCalled(int transitionKey)142         public boolean wasEndCalled(int transitionKey) {
143             return ((TransitionCalledListener)mListeners[transitionKey]).endLatch.getCount() == 0;
144         }
145 
waitForStart(int transitionKey)146         public boolean waitForStart(int transitionKey)
147                 throws InterruptedException {
148             TransitionCalledListener l = ((TransitionCalledListener)mListeners[transitionKey]);
149             return l.startLatch.await(500,TimeUnit.MILLISECONDS);
150         }
151 
waitForEnd(int transitionKey)152         public boolean waitForEnd(int transitionKey)
153                 throws InterruptedException {
154             TransitionCalledListener l = ((TransitionCalledListener)mListeners[transitionKey]);
155             return l.endLatch.await(500,TimeUnit.MILLISECONDS);
156         }
157 
loadTransition(int key)158         private Transition loadTransition(int key) {
159             final int id = mTransitionIds[key];
160             if (id == 0) {
161                 return null;
162             }
163             Transition transition = TransitionInflater.from(getActivity()).inflateTransition(id);
164             transition.addListener(((TransitionCalledListener)mListeners[key]));
165             return transition;
166         }
167 
168         private class TransitionCalledListener implements TransitionListener {
169             public CountDownLatch startLatch = new CountDownLatch(1);
170             public CountDownLatch endLatch = new CountDownLatch(1);
171 
TransitionCalledListener()172             public TransitionCalledListener() {
173             }
174 
175             @Override
onTransitionStart(Transition transition)176             public void onTransitionStart(Transition transition) {
177                 startLatch.countDown();
178             }
179 
180             @Override
onTransitionEnd(Transition transition)181             public void onTransitionEnd(Transition transition) {
182                 endLatch.countDown();
183             }
184 
185             @Override
onTransitionCancel(Transition transition)186             public void onTransitionCancel(Transition transition) {
187             }
188 
189             @Override
onTransitionPause(Transition transition)190             public void onTransitionPause(Transition transition) {
191             }
192 
193             @Override
onTransitionResume(Transition transition)194             public void onTransitionResume(Transition transition) {
195             }
196         }
197     }
198 
199     public static class ParentFragment extends Fragment {
200         static final String CHILD_FRAGMENT_TAG = "childFragment";
201         public boolean wasAttachedInTime;
202 
203         private boolean mRetainChild;
204 
205         @Override
onCreate(Bundle savedInstanceState)206         public void onCreate(Bundle savedInstanceState) {
207             super.onCreate(savedInstanceState);
208 
209             ChildFragment f = getChildFragment();
210             if (f == null) {
211                 f = new ChildFragment();
212                 if (mRetainChild) {
213                     f.setRetainInstance(true);
214                 }
215                 getChildFragmentManager().beginTransaction().add(f, CHILD_FRAGMENT_TAG).commitNow();
216             }
217             wasAttachedInTime = f.attached;
218         }
219 
getChildFragment()220         public ChildFragment getChildFragment() {
221             return (ChildFragment) getChildFragmentManager().findFragmentByTag(CHILD_FRAGMENT_TAG);
222         }
223 
setRetainChildInstance(boolean retainChild)224         public void setRetainChildInstance(boolean retainChild) {
225             mRetainChild = retainChild;
226         }
227     }
228 
229     public static class ChildFragment extends Fragment {
230         private OnAttachListener mOnAttachListener;
231 
232         public boolean attached;
233         public boolean onActivityResultCalled;
234         public int onActivityResultRequestCode;
235         public int onActivityResultResultCode;
236 
237         @Override
onAttach(Context activity)238         public void onAttach(Context activity) {
239             super.onAttach(activity);
240             attached = true;
241             if (mOnAttachListener != null) {
242                 mOnAttachListener.onAttach(activity, this);
243             }
244         }
245 
setOnAttachListener(OnAttachListener listener)246         public void setOnAttachListener(OnAttachListener listener) {
247             mOnAttachListener = listener;
248         }
249 
250         public interface OnAttachListener {
onAttach(Context activity, ChildFragment fragment)251             void onAttach(Context activity, ChildFragment fragment);
252         }
253 
254         @Override
onActivityResult(int requestCode, int resultCode, Intent data)255         public void onActivityResult(int requestCode, int resultCode, Intent data) {
256             onActivityResultCalled = true;
257             onActivityResultRequestCode = requestCode;
258             onActivityResultResultCode = resultCode;
259         }
260     }
261 }
262