| /* |
| * Copyright (C) 2006 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package android.widget; |
| |
| |
| import android.content.Context; |
| import android.content.res.TypedArray; |
| import android.util.AttributeSet; |
| import android.view.View; |
| import android.view.ViewGroup; |
| import android.view.animation.Animation; |
| import android.view.animation.AnimationUtils; |
| |
| /** |
| * Base class for a {@link FrameLayout} container that will perform animations |
| * when switching between its views. |
| * |
| * @attr ref android.R.styleable#ViewAnimator_inAnimation |
| * @attr ref android.R.styleable#ViewAnimator_outAnimation |
| */ |
| public class ViewAnimator extends FrameLayout { |
| |
| int mWhichChild = 0; |
| boolean mFirstTime = true; |
| boolean mAnimateFirstTime = true; |
| |
| Animation mInAnimation; |
| Animation mOutAnimation; |
| |
| public ViewAnimator(Context context) { |
| super(context); |
| initViewAnimator(context, null); |
| } |
| |
| public ViewAnimator(Context context, AttributeSet attrs) { |
| super(context, attrs); |
| |
| TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.ViewAnimator); |
| int resource = a.getResourceId(com.android.internal.R.styleable.ViewAnimator_inAnimation, 0); |
| if (resource > 0) { |
| setInAnimation(context, resource); |
| } |
| |
| resource = a.getResourceId(com.android.internal.R.styleable.ViewAnimator_outAnimation, 0); |
| if (resource > 0) { |
| setOutAnimation(context, resource); |
| } |
| a.recycle(); |
| |
| initViewAnimator(context, attrs); |
| } |
| |
| /** |
| * Initialize this {@link ViewAnimator}, possibly setting |
| * {@link #setMeasureAllChildren(boolean)} based on {@link FrameLayout} flags. |
| */ |
| private void initViewAnimator(Context context, AttributeSet attrs) { |
| if (attrs == null) { |
| // For compatibility, always measure children when undefined. |
| mMeasureAllChildren = true; |
| return; |
| } |
| |
| // For compatibility, default to measure children, but allow XML |
| // attribute to override. |
| final TypedArray a = context.obtainStyledAttributes(attrs, |
| com.android.internal.R.styleable.FrameLayout); |
| final boolean measureAllChildren = a.getBoolean( |
| com.android.internal.R.styleable.FrameLayout_measureAllChildren, true); |
| setMeasureAllChildren(measureAllChildren); |
| a.recycle(); |
| } |
| |
| /** |
| * Sets which child view will be displayed. |
| * |
| * @param whichChild the index of the child view to display |
| */ |
| public void setDisplayedChild(int whichChild) { |
| mWhichChild = whichChild; |
| if (whichChild >= getChildCount()) { |
| mWhichChild = 0; |
| } else if (whichChild < 0) { |
| mWhichChild = getChildCount() - 1; |
| } |
| boolean hasFocus = getFocusedChild() != null; |
| // This will clear old focus if we had it |
| showOnly(mWhichChild); |
| if (hasFocus) { |
| // Try to retake focus if we had it |
| requestFocus(FOCUS_FORWARD); |
| } |
| } |
| |
| /** |
| * Returns the index of the currently displayed child view. |
| */ |
| public int getDisplayedChild() { |
| return mWhichChild; |
| } |
| |
| /** |
| * Manually shows the next child. |
| */ |
| public void showNext() { |
| setDisplayedChild(mWhichChild + 1); |
| } |
| |
| /** |
| * Manually shows the previous child. |
| */ |
| public void showPrevious() { |
| setDisplayedChild(mWhichChild - 1); |
| } |
| |
| /** |
| * Shows only the specified child. The other displays Views exit the screen |
| * with the {@link #getOutAnimation() out animation} and the specified child |
| * enters the screen with the {@link #getInAnimation() in animation}. |
| * |
| * @param childIndex The index of the child to be shown. |
| */ |
| void showOnly(int childIndex) { |
| final int count = getChildCount(); |
| for (int i = 0; i < count; i++) { |
| final View child = getChildAt(i); |
| final boolean checkForFirst = (!mFirstTime || mAnimateFirstTime); |
| if (i == childIndex) { |
| if (checkForFirst && mInAnimation != null) { |
| child.startAnimation(mInAnimation); |
| } |
| child.setVisibility(View.VISIBLE); |
| mFirstTime = false; |
| } else { |
| if (checkForFirst && mOutAnimation != null && child.getVisibility() == View.VISIBLE) { |
| child.startAnimation(mOutAnimation); |
| } else if (child.getAnimation() == mInAnimation) |
| child.clearAnimation(); |
| child.setVisibility(View.GONE); |
| } |
| } |
| } |
| |
| @Override |
| public void addView(View child, int index, ViewGroup.LayoutParams params) { |
| super.addView(child, index, params); |
| if (getChildCount() == 1) { |
| child.setVisibility(View.VISIBLE); |
| } else { |
| child.setVisibility(View.GONE); |
| } |
| } |
| |
| @Override |
| public void removeAllViews() { |
| super.removeAllViews(); |
| mWhichChild = 0; |
| mFirstTime = true; |
| } |
| |
| @Override |
| public void removeView(View view) { |
| final int index = indexOfChild(view); |
| if (index >= 0) { |
| removeViewAt(index); |
| } |
| } |
| |
| @Override |
| public void removeViewAt(int index) { |
| super.removeViewAt(index); |
| final int childCount = getChildCount(); |
| if (childCount == 0) { |
| mWhichChild = 0; |
| mFirstTime = true; |
| } else if (mWhichChild >= childCount) { |
| // Displayed is above child count, so float down to top of stack |
| setDisplayedChild(childCount - 1); |
| } else if (mWhichChild == index) { |
| // Displayed was removed, so show the new child living in its place |
| setDisplayedChild(mWhichChild); |
| } |
| } |
| |
| public void removeViewInLayout(View view) { |
| removeView(view); |
| } |
| |
| public void removeViews(int start, int count) { |
| super.removeViews(start, count); |
| if (getChildCount() == 0) { |
| mWhichChild = 0; |
| mFirstTime = true; |
| } else if (mWhichChild >= start && mWhichChild < start + count) { |
| // Try showing new displayed child, wrapping if needed |
| setDisplayedChild(mWhichChild); |
| } |
| } |
| |
| public void removeViewsInLayout(int start, int count) { |
| removeViews(start, count); |
| } |
| |
| /** |
| * Returns the View corresponding to the currently displayed child. |
| * |
| * @return The View currently displayed. |
| * |
| * @see #getDisplayedChild() |
| */ |
| public View getCurrentView() { |
| return getChildAt(mWhichChild); |
| } |
| |
| /** |
| * Returns the current animation used to animate a View that enters the screen. |
| * |
| * @return An Animation or null if none is set. |
| * |
| * @see #setInAnimation(android.view.animation.Animation) |
| * @see #setInAnimation(android.content.Context, int) |
| */ |
| public Animation getInAnimation() { |
| return mInAnimation; |
| } |
| |
| /** |
| * Specifies the animation used to animate a View that enters the screen. |
| * |
| * @param inAnimation The animation started when a View enters the screen. |
| * |
| * @see #getInAnimation() |
| * @see #setInAnimation(android.content.Context, int) |
| */ |
| public void setInAnimation(Animation inAnimation) { |
| mInAnimation = inAnimation; |
| } |
| |
| /** |
| * Returns the current animation used to animate a View that exits the screen. |
| * |
| * @return An Animation or null if none is set. |
| * |
| * @see #setOutAnimation(android.view.animation.Animation) |
| * @see #setOutAnimation(android.content.Context, int) |
| */ |
| public Animation getOutAnimation() { |
| return mOutAnimation; |
| } |
| |
| /** |
| * Specifies the animation used to animate a View that exit the screen. |
| * |
| * @param outAnimation The animation started when a View exit the screen. |
| * |
| * @see #getOutAnimation() |
| * @see #setOutAnimation(android.content.Context, int) |
| */ |
| public void setOutAnimation(Animation outAnimation) { |
| mOutAnimation = outAnimation; |
| } |
| |
| /** |
| * Specifies the animation used to animate a View that enters the screen. |
| * |
| * @param context The application's environment. |
| * @param resourceID The resource id of the animation. |
| * |
| * @see #getInAnimation() |
| * @see #setInAnimation(android.view.animation.Animation) |
| */ |
| public void setInAnimation(Context context, int resourceID) { |
| setInAnimation(AnimationUtils.loadAnimation(context, resourceID)); |
| } |
| |
| /** |
| * Specifies the animation used to animate a View that exit the screen. |
| * |
| * @param context The application's environment. |
| * @param resourceID The resource id of the animation. |
| * |
| * @see #getOutAnimation() |
| * @see #setOutAnimation(android.view.animation.Animation) |
| */ |
| public void setOutAnimation(Context context, int resourceID) { |
| setOutAnimation(AnimationUtils.loadAnimation(context, resourceID)); |
| } |
| |
| /** |
| * Indicates whether the current View should be animated the first time |
| * the ViewAnimation is displayed. |
| * |
| * @param animate True to animate the current View the first time it is displayed, |
| * false otherwise. |
| */ |
| public void setAnimateFirstView(boolean animate) { |
| mAnimateFirstTime = animate; |
| } |
| |
| @Override |
| public int getBaseline() { |
| return (getCurrentView() != null) ? getCurrentView().getBaseline() : super.getBaseline(); |
| } |
| } |