• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006 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 
17 package android.widget;
18 
19 
20 import android.content.Context;
21 import android.content.res.TypedArray;
22 import android.util.AttributeSet;
23 import android.view.View;
24 import android.view.ViewGroup;
25 import android.view.animation.Animation;
26 import android.view.animation.AnimationUtils;
27 
28 /**
29  * Base class for a {@link FrameLayout} container that will perform animations
30  * when switching between its views.
31  *
32  * @attr ref android.R.styleable#ViewAnimator_inAnimation
33  * @attr ref android.R.styleable#ViewAnimator_outAnimation
34  */
35 public class ViewAnimator extends FrameLayout {
36 
37     int mWhichChild = 0;
38     boolean mFirstTime = true;
39     boolean mAnimateFirstTime = true;
40 
41     Animation mInAnimation;
42     Animation mOutAnimation;
43 
ViewAnimator(Context context)44     public ViewAnimator(Context context) {
45         super(context);
46         initViewAnimator();
47     }
48 
ViewAnimator(Context context, AttributeSet attrs)49     public ViewAnimator(Context context, AttributeSet attrs) {
50         super(context, attrs);
51 
52         TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.ViewAnimator);
53         int resource = a.getResourceId(com.android.internal.R.styleable.ViewAnimator_inAnimation, 0);
54         if (resource > 0) {
55             setInAnimation(context, resource);
56         }
57 
58         resource = a.getResourceId(com.android.internal.R.styleable.ViewAnimator_outAnimation, 0);
59         if (resource > 0) {
60             setOutAnimation(context, resource);
61         }
62         a.recycle();
63 
64         initViewAnimator();
65     }
66 
initViewAnimator()67     private void initViewAnimator() {
68         mMeasureAllChildren = true;
69     }
70 
71     /**
72      * Sets which child view will be displayed.
73      *
74      * @param whichChild the index of the child view to display
75      */
setDisplayedChild(int whichChild)76     public void setDisplayedChild(int whichChild) {
77         mWhichChild = whichChild;
78         if (whichChild >= getChildCount()) {
79             mWhichChild = 0;
80         } else if (whichChild < 0) {
81             mWhichChild = getChildCount() - 1;
82         }
83         boolean hasFocus = getFocusedChild() != null;
84         // This will clear old focus if we had it
85         showOnly(mWhichChild);
86         if (hasFocus) {
87             // Try to retake focus if we had it
88             requestFocus(FOCUS_FORWARD);
89         }
90     }
91 
92     /**
93      * Returns the index of the currently displayed child view.
94      */
getDisplayedChild()95     public int getDisplayedChild() {
96         return mWhichChild;
97     }
98 
99     /**
100      * Manually shows the next child.
101      */
showNext()102     public void showNext() {
103         setDisplayedChild(mWhichChild + 1);
104     }
105 
106     /**
107      * Manually shows the previous child.
108      */
showPrevious()109     public void showPrevious() {
110         setDisplayedChild(mWhichChild - 1);
111     }
112 
113     /**
114      * Shows only the specified child. The other displays Views exit the screen
115      * with the {@link #getOutAnimation() out animation} and the specified child
116      * enters the screen with the {@link #getInAnimation() in animation}.
117      *
118      * @param childIndex The index of the child to be shown.
119      */
showOnly(int childIndex)120     void showOnly(int childIndex) {
121         final int count = getChildCount();
122         for (int i = 0; i < count; i++) {
123             final View child = getChildAt(i);
124             if (i == childIndex) {
125                 if ((!mFirstTime || mAnimateFirstTime) && mInAnimation != null) {
126                     child.startAnimation(mInAnimation);
127                 }
128                 child.setVisibility(View.VISIBLE);
129                 mFirstTime = false;
130             } else {
131                 if (mOutAnimation != null && child.getVisibility() == View.VISIBLE) {
132                     child.startAnimation(mOutAnimation);
133                 } else if (child.getAnimation() == mInAnimation)
134                     child.clearAnimation();
135                 child.setVisibility(View.GONE);
136             }
137         }
138     }
139 
140     @Override
addView(View child, int index, ViewGroup.LayoutParams params)141     public void addView(View child, int index, ViewGroup.LayoutParams params) {
142         super.addView(child, index, params);
143         if (getChildCount() == 1) {
144             child.setVisibility(View.VISIBLE);
145         } else {
146             child.setVisibility(View.GONE);
147         }
148     }
149 
150     @Override
removeAllViews()151     public void removeAllViews() {
152         super.removeAllViews();
153         mWhichChild = 0;
154         mFirstTime = true;
155     }
156 
157     @Override
removeView(View view)158     public void removeView(View view) {
159         final int index = indexOfChild(view);
160         if (index >= 0) {
161             removeViewAt(index);
162         }
163     }
164 
165     @Override
removeViewAt(int index)166     public void removeViewAt(int index) {
167         super.removeViewAt(index);
168         final int childCount = getChildCount();
169         if (childCount == 0) {
170             mWhichChild = 0;
171             mFirstTime = true;
172         } else if (mWhichChild >= childCount) {
173             // Displayed is above child count, so float down to top of stack
174             setDisplayedChild(childCount - 1);
175         } else if (mWhichChild == index) {
176             // Displayed was removed, so show the new child living in its place
177             setDisplayedChild(mWhichChild);
178         }
179     }
180 
removeViewInLayout(View view)181     public void removeViewInLayout(View view) {
182         removeView(view);
183     }
184 
removeViews(int start, int count)185     public void removeViews(int start, int count) {
186         super.removeViews(start, count);
187         if (getChildCount() == 0) {
188             mWhichChild = 0;
189             mFirstTime = true;
190         } else if (mWhichChild >= start && mWhichChild < start + count) {
191             // Try showing new displayed child, wrapping if needed
192             setDisplayedChild(mWhichChild);
193         }
194     }
195 
removeViewsInLayout(int start, int count)196     public void removeViewsInLayout(int start, int count) {
197         removeViews(start, count);
198     }
199 
200     /**
201      * Returns the View corresponding to the currently displayed child.
202      *
203      * @return The View currently displayed.
204      *
205      * @see #getDisplayedChild()
206      */
getCurrentView()207     public View getCurrentView() {
208         return getChildAt(mWhichChild);
209     }
210 
211     /**
212      * Returns the current animation used to animate a View that enters the screen.
213      *
214      * @return An Animation or null if none is set.
215      *
216      * @see #setInAnimation(android.view.animation.Animation)
217      * @see #setInAnimation(android.content.Context, int)
218      */
getInAnimation()219     public Animation getInAnimation() {
220         return mInAnimation;
221     }
222 
223     /**
224      * Specifies the animation used to animate a View that enters the screen.
225      *
226      * @param inAnimation The animation started when a View enters the screen.
227      *
228      * @see #getInAnimation()
229      * @see #setInAnimation(android.content.Context, int)
230      */
setInAnimation(Animation inAnimation)231     public void setInAnimation(Animation inAnimation) {
232         mInAnimation = inAnimation;
233     }
234 
235     /**
236      * Returns the current animation used to animate a View that exits the screen.
237      *
238      * @return An Animation or null if none is set.
239      *
240      * @see #setOutAnimation(android.view.animation.Animation)
241      * @see #setOutAnimation(android.content.Context, int)
242      */
getOutAnimation()243     public Animation getOutAnimation() {
244         return mOutAnimation;
245     }
246 
247     /**
248      * Specifies the animation used to animate a View that exit the screen.
249      *
250      * @param outAnimation The animation started when a View exit the screen.
251      *
252      * @see #getOutAnimation()
253      * @see #setOutAnimation(android.content.Context, int)
254      */
setOutAnimation(Animation outAnimation)255     public void setOutAnimation(Animation outAnimation) {
256         mOutAnimation = outAnimation;
257     }
258 
259     /**
260      * Specifies the animation used to animate a View that enters the screen.
261      *
262      * @param context The application's environment.
263      * @param resourceID The resource id of the animation.
264      *
265      * @see #getInAnimation()
266      * @see #setInAnimation(android.view.animation.Animation)
267      */
setInAnimation(Context context, int resourceID)268     public void setInAnimation(Context context, int resourceID) {
269         setInAnimation(AnimationUtils.loadAnimation(context, resourceID));
270     }
271 
272     /**
273      * Specifies the animation used to animate a View that exit the screen.
274      *
275      * @param context The application's environment.
276      * @param resourceID The resource id of the animation.
277      *
278      * @see #getOutAnimation()
279      * @see #setOutAnimation(android.view.animation.Animation)
280      */
setOutAnimation(Context context, int resourceID)281     public void setOutAnimation(Context context, int resourceID) {
282         setOutAnimation(AnimationUtils.loadAnimation(context, resourceID));
283     }
284 
285     /**
286      * Indicates whether the current View should be animated the first time
287      * the ViewAnimation is displayed.
288      *
289      * @param animate True to animate the current View the first time it is displayed,
290      *                false otherwise.
291      */
setAnimateFirstView(boolean animate)292     public void setAnimateFirstView(boolean animate) {
293         mAnimateFirstTime = animate;
294     }
295 
296     @Override
getBaseline()297     public int getBaseline() {
298         return (getCurrentView() != null) ? getCurrentView().getBaseline() : super.getBaseline();
299     }
300 }
301