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