| /* |
| * Copyright (C) 2007 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.view.animation; |
| |
| import android.view.View; |
| import android.view.ViewGroup; |
| import android.content.Context; |
| import android.content.res.TypedArray; |
| import android.util.AttributeSet; |
| |
| import java.util.Random; |
| |
| /** |
| * A layout animation controller is used to animated a grid layout's children. |
| * |
| * While {@link LayoutAnimationController} relies only on the index of the child |
| * in the view group to compute the animation delay, this class uses both the |
| * X and Y coordinates of the child within a grid. |
| * |
| * In addition, the animation direction can be controlled. The default direction |
| * is <code>DIRECTION_LEFT_TO_RIGHT | DIRECTION_TOP_TO_BOTTOM</code>. You can |
| * also set the animation priority to columns or rows. The default priority is |
| * none. |
| * |
| * Information used to compute the animation delay of each child are stored |
| * in an instance of |
| * {@link android.view.animation.GridLayoutAnimationController.AnimationParameters}, |
| * itself stored in the {@link android.view.ViewGroup.LayoutParams} of the view. |
| * |
| * @see LayoutAnimationController |
| * @see android.widget.GridView |
| * |
| * @attr ref android.R.styleable#GridLayoutAnimation_columnDelay |
| * @attr ref android.R.styleable#GridLayoutAnimation_rowDelay |
| * @attr ref android.R.styleable#GridLayoutAnimation_direction |
| * @attr ref android.R.styleable#GridLayoutAnimation_directionPriority |
| */ |
| public class GridLayoutAnimationController extends LayoutAnimationController { |
| /** |
| * Animates the children starting from the left of the grid to the right. |
| */ |
| public static final int DIRECTION_LEFT_TO_RIGHT = 0x0; |
| |
| /** |
| * Animates the children starting from the right of the grid to the left. |
| */ |
| public static final int DIRECTION_RIGHT_TO_LEFT = 0x1; |
| |
| /** |
| * Animates the children starting from the top of the grid to the bottom. |
| */ |
| public static final int DIRECTION_TOP_TO_BOTTOM = 0x0; |
| |
| /** |
| * Animates the children starting from the bottom of the grid to the top. |
| */ |
| public static final int DIRECTION_BOTTOM_TO_TOP = 0x2; |
| |
| /** |
| * Bitmask used to retrieve the horizontal component of the direction. |
| */ |
| public static final int DIRECTION_HORIZONTAL_MASK = 0x1; |
| |
| /** |
| * Bitmask used to retrieve the vertical component of the direction. |
| */ |
| public static final int DIRECTION_VERTICAL_MASK = 0x2; |
| |
| /** |
| * Rows and columns are animated at the same time. |
| */ |
| public static final int PRIORITY_NONE = 0; |
| |
| /** |
| * Columns are animated first. |
| */ |
| public static final int PRIORITY_COLUMN = 1; |
| |
| /** |
| * Rows are animated first. |
| */ |
| public static final int PRIORITY_ROW = 2; |
| |
| private float mColumnDelay; |
| private float mRowDelay; |
| |
| private int mDirection; |
| private int mDirectionPriority; |
| |
| /** |
| * Creates a new grid layout animation controller from external resources. |
| * |
| * @param context the Context the view group is running in, through which |
| * it can access the resources |
| * @param attrs the attributes of the XML tag that is inflating the |
| * layout animation controller |
| */ |
| public GridLayoutAnimationController(Context context, AttributeSet attrs) { |
| super(context, attrs); |
| |
| TypedArray a = context.obtainStyledAttributes(attrs, |
| com.android.internal.R.styleable.GridLayoutAnimation); |
| |
| Animation.Description d = Animation.Description.parseValue( |
| a.peekValue(com.android.internal.R.styleable.GridLayoutAnimation_columnDelay)); |
| mColumnDelay = d.value; |
| d = Animation.Description.parseValue( |
| a.peekValue(com.android.internal.R.styleable.GridLayoutAnimation_rowDelay)); |
| mRowDelay = d.value; |
| //noinspection PointlessBitwiseExpression |
| mDirection = a.getInt(com.android.internal.R.styleable.GridLayoutAnimation_direction, |
| DIRECTION_LEFT_TO_RIGHT | DIRECTION_TOP_TO_BOTTOM); |
| mDirectionPriority = a.getInt(com.android.internal.R.styleable.GridLayoutAnimation_directionPriority, |
| PRIORITY_NONE); |
| |
| a.recycle(); |
| } |
| |
| /** |
| * Creates a new layout animation controller with a delay of 50% |
| * for both rows and columns and the specified animation. |
| * |
| * @param animation the animation to use on each child of the view group |
| */ |
| public GridLayoutAnimationController(Animation animation) { |
| this(animation, 0.5f, 0.5f); |
| } |
| |
| /** |
| * Creates a new layout animation controller with the specified delays |
| * and the specified animation. |
| * |
| * @param animation the animation to use on each child of the view group |
| * @param columnDelay the delay by which each column animation must be offset |
| * @param rowDelay the delay by which each row animation must be offset |
| */ |
| public GridLayoutAnimationController(Animation animation, float columnDelay, float rowDelay) { |
| super(animation); |
| mColumnDelay = columnDelay; |
| mRowDelay = rowDelay; |
| } |
| |
| /** |
| * Returns the delay by which the children's animation are offset from one |
| * column to the other. The delay is expressed as a fraction of the |
| * animation duration. |
| * |
| * @return a fraction of the animation duration |
| * |
| * @see #setColumnDelay(float) |
| * @see #getRowDelay() |
| * @see #setRowDelay(float) |
| */ |
| public float getColumnDelay() { |
| return mColumnDelay; |
| } |
| |
| /** |
| * Sets the delay, as a fraction of the animation duration, by which the |
| * children's animations are offset from one column to the other. |
| * |
| * @param columnDelay a fraction of the animation duration |
| * |
| * @see #getColumnDelay() |
| * @see #getRowDelay() |
| * @see #setRowDelay(float) |
| */ |
| public void setColumnDelay(float columnDelay) { |
| mColumnDelay = columnDelay; |
| } |
| |
| /** |
| * Returns the delay by which the children's animation are offset from one |
| * row to the other. The delay is expressed as a fraction of the |
| * animation duration. |
| * |
| * @return a fraction of the animation duration |
| * |
| * @see #setRowDelay(float) |
| * @see #getColumnDelay() |
| * @see #setColumnDelay(float) |
| */ |
| public float getRowDelay() { |
| return mRowDelay; |
| } |
| |
| /** |
| * Sets the delay, as a fraction of the animation duration, by which the |
| * children's animations are offset from one row to the other. |
| * |
| * @param rowDelay a fraction of the animation duration |
| * |
| * @see #getRowDelay() |
| * @see #getColumnDelay() |
| * @see #setColumnDelay(float) |
| */ |
| public void setRowDelay(float rowDelay) { |
| mRowDelay = rowDelay; |
| } |
| |
| /** |
| * Returns the direction of the animation. {@link #DIRECTION_HORIZONTAL_MASK} |
| * and {@link #DIRECTION_VERTICAL_MASK} can be used to retrieve the |
| * horizontal and vertical components of the direction. |
| * |
| * @return the direction of the animation |
| * |
| * @see #setDirection(int) |
| * @see #DIRECTION_BOTTOM_TO_TOP |
| * @see #DIRECTION_TOP_TO_BOTTOM |
| * @see #DIRECTION_LEFT_TO_RIGHT |
| * @see #DIRECTION_RIGHT_TO_LEFT |
| * @see #DIRECTION_HORIZONTAL_MASK |
| * @see #DIRECTION_VERTICAL_MASK |
| */ |
| public int getDirection() { |
| return mDirection; |
| } |
| |
| /** |
| * Sets the direction of the animation. The direction is expressed as an |
| * integer containing a horizontal and vertical component. For instance, |
| * <code>DIRECTION_BOTTOM_TO_TOP | DIRECTION_RIGHT_TO_LEFT</code>. |
| * |
| * @param direction the direction of the animation |
| * |
| * @see #getDirection() |
| * @see #DIRECTION_BOTTOM_TO_TOP |
| * @see #DIRECTION_TOP_TO_BOTTOM |
| * @see #DIRECTION_LEFT_TO_RIGHT |
| * @see #DIRECTION_RIGHT_TO_LEFT |
| * @see #DIRECTION_HORIZONTAL_MASK |
| * @see #DIRECTION_VERTICAL_MASK |
| */ |
| public void setDirection(int direction) { |
| mDirection = direction; |
| } |
| |
| /** |
| * Returns the direction priority for the animation. The priority can |
| * be either {@link #PRIORITY_NONE}, {@link #PRIORITY_COLUMN} or |
| * {@link #PRIORITY_ROW}. |
| * |
| * @return the priority of the animation direction |
| * |
| * @see #setDirectionPriority(int) |
| * @see #PRIORITY_COLUMN |
| * @see #PRIORITY_NONE |
| * @see #PRIORITY_ROW |
| */ |
| public int getDirectionPriority() { |
| return mDirectionPriority; |
| } |
| |
| /** |
| * Specifies the direction priority of the animation. For instance, |
| * {@link #PRIORITY_COLUMN} will give priority to columns: the animation |
| * will first play on the column, then on the rows.Z |
| * |
| * @param directionPriority the direction priority of the animation |
| * |
| * @see #getDirectionPriority() |
| * @see #PRIORITY_COLUMN |
| * @see #PRIORITY_NONE |
| * @see #PRIORITY_ROW |
| */ |
| public void setDirectionPriority(int directionPriority) { |
| mDirectionPriority = directionPriority; |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public boolean willOverlap() { |
| return mColumnDelay < 1.0f || mRowDelay < 1.0f; |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| protected long getDelayForView(View view) { |
| ViewGroup.LayoutParams lp = view.getLayoutParams(); |
| AnimationParameters params = (AnimationParameters) lp.layoutAnimationParameters; |
| |
| if (params == null) { |
| return 0; |
| } |
| |
| final int column = getTransformedColumnIndex(params); |
| final int row = getTransformedRowIndex(params); |
| |
| final int rowsCount = params.rowsCount; |
| final int columnsCount = params.columnsCount; |
| |
| final long duration = mAnimation.getDuration(); |
| final float columnDelay = mColumnDelay * duration; |
| final float rowDelay = mRowDelay * duration; |
| |
| float totalDelay; |
| long viewDelay; |
| |
| if (mInterpolator == null) { |
| mInterpolator = new LinearInterpolator(); |
| } |
| |
| switch (mDirectionPriority) { |
| case PRIORITY_COLUMN: |
| viewDelay = (long) (row * rowDelay + column * rowsCount * rowDelay); |
| totalDelay = rowsCount * rowDelay + columnsCount * rowsCount * rowDelay; |
| break; |
| case PRIORITY_ROW: |
| viewDelay = (long) (column * columnDelay + row * columnsCount * columnDelay); |
| totalDelay = columnsCount * columnDelay + rowsCount * columnsCount * columnDelay; |
| break; |
| case PRIORITY_NONE: |
| default: |
| viewDelay = (long) (column * columnDelay + row * rowDelay); |
| totalDelay = columnsCount * columnDelay + rowsCount * rowDelay; |
| break; |
| } |
| |
| float normalizedDelay = viewDelay / totalDelay; |
| normalizedDelay = mInterpolator.getInterpolation(normalizedDelay); |
| |
| return (long) (normalizedDelay * totalDelay); |
| } |
| |
| private int getTransformedColumnIndex(AnimationParameters params) { |
| int index; |
| switch (getOrder()) { |
| case ORDER_REVERSE: |
| index = params.columnsCount - 1 - params.column; |
| break; |
| case ORDER_RANDOM: |
| if (mRandomizer == null) { |
| mRandomizer = new Random(); |
| } |
| index = (int) (params.columnsCount * mRandomizer.nextFloat()); |
| break; |
| case ORDER_NORMAL: |
| default: |
| index = params.column; |
| break; |
| } |
| |
| int direction = mDirection & DIRECTION_HORIZONTAL_MASK; |
| if (direction == DIRECTION_RIGHT_TO_LEFT) { |
| index = params.columnsCount - 1 - index; |
| } |
| |
| return index; |
| } |
| |
| private int getTransformedRowIndex(AnimationParameters params) { |
| int index; |
| switch (getOrder()) { |
| case ORDER_REVERSE: |
| index = params.rowsCount - 1 - params.row; |
| break; |
| case ORDER_RANDOM: |
| if (mRandomizer == null) { |
| mRandomizer = new Random(); |
| } |
| index = (int) (params.rowsCount * mRandomizer.nextFloat()); |
| break; |
| case ORDER_NORMAL: |
| default: |
| index = params.row; |
| break; |
| } |
| |
| int direction = mDirection & DIRECTION_VERTICAL_MASK; |
| if (direction == DIRECTION_BOTTOM_TO_TOP) { |
| index = params.rowsCount - 1 - index; |
| } |
| |
| return index; |
| } |
| |
| /** |
| * The set of parameters that has to be attached to each view contained in |
| * the view group animated by the grid layout animation controller. These |
| * parameters are used to compute the start time of each individual view's |
| * animation. |
| */ |
| public static class AnimationParameters extends |
| LayoutAnimationController.AnimationParameters { |
| /** |
| * The view group's column to which the view belongs. |
| */ |
| public int column; |
| |
| /** |
| * The view group's row to which the view belongs. |
| */ |
| public int row; |
| |
| /** |
| * The number of columns in the view's enclosing grid layout. |
| */ |
| public int columnsCount; |
| |
| /** |
| * The number of rows in the view's enclosing grid layout. |
| */ |
| public int rowsCount; |
| } |
| } |