Home | History | Annotate | Download | only in animation
      1 /*
      2  * Copyright (C) 2007 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.view.animation;
     18 
     19 import android.content.Context;
     20 import android.content.res.TypedArray;
     21 import android.util.AttributeSet;
     22 import android.view.View;
     23 import android.view.ViewGroup;
     24 
     25 import java.util.Random;
     26 
     27 /**
     28  * A layout animation controller is used to animated a grid layout's children.
     29  *
     30  * While {@link LayoutAnimationController} relies only on the index of the child
     31  * in the view group to compute the animation delay, this class uses both the
     32  * X and Y coordinates of the child within a grid.
     33  *
     34  * In addition, the animation direction can be controlled. The default direction
     35  * is <code>DIRECTION_LEFT_TO_RIGHT | DIRECTION_TOP_TO_BOTTOM</code>. You can
     36  * also set the animation priority to columns or rows. The default priority is
     37  * none.
     38  *
     39  * Information used to compute the animation delay of each child are stored
     40  * in an instance of
     41  * {@link android.view.animation.GridLayoutAnimationController.AnimationParameters},
     42  * itself stored in the {@link android.view.ViewGroup.LayoutParams} of the view.
     43  *
     44  * @see LayoutAnimationController
     45  * @see android.widget.GridView
     46  *
     47  * @attr ref android.R.styleable#GridLayoutAnimation_columnDelay
     48  * @attr ref android.R.styleable#GridLayoutAnimation_rowDelay
     49  * @attr ref android.R.styleable#GridLayoutAnimation_direction
     50  * @attr ref android.R.styleable#GridLayoutAnimation_directionPriority
     51  */
     52 public class GridLayoutAnimationController extends LayoutAnimationController {
     53     /**
     54      * Animates the children starting from the left of the grid to the right.
     55      */
     56     public static final int DIRECTION_LEFT_TO_RIGHT = 0x0;
     57 
     58     /**
     59      * Animates the children starting from the right of the grid to the left.
     60      */
     61     public static final int DIRECTION_RIGHT_TO_LEFT = 0x1;
     62 
     63     /**
     64      * Animates the children starting from the top of the grid to the bottom.
     65      */
     66     public static final int DIRECTION_TOP_TO_BOTTOM = 0x0;
     67 
     68     /**
     69      * Animates the children starting from the bottom of the grid to the top.
     70      */
     71     public static final int DIRECTION_BOTTOM_TO_TOP = 0x2;
     72 
     73     /**
     74      * Bitmask used to retrieve the horizontal component of the direction.
     75      */
     76     public static final int DIRECTION_HORIZONTAL_MASK = 0x1;
     77 
     78     /**
     79      * Bitmask used to retrieve the vertical component of the direction.
     80      */
     81     public static final int DIRECTION_VERTICAL_MASK   = 0x2;
     82 
     83     /**
     84      * Rows and columns are animated at the same time.
     85      */
     86     public static final int PRIORITY_NONE   = 0;
     87 
     88     /**
     89      * Columns are animated first.
     90      */
     91     public static final int PRIORITY_COLUMN = 1;
     92 
     93     /**
     94      * Rows are animated first.
     95      */
     96     public static final int PRIORITY_ROW    = 2;
     97 
     98     private float mColumnDelay;
     99     private float mRowDelay;
    100 
    101     private int mDirection;
    102     private int mDirectionPriority;
    103 
    104     /**
    105      * Creates a new grid layout animation controller from external resources.
    106      *
    107      * @param context the Context the view  group is running in, through which
    108      *        it can access the resources
    109      * @param attrs the attributes of the XML tag that is inflating the
    110      *        layout animation controller
    111      */
    112     public GridLayoutAnimationController(Context context, AttributeSet attrs) {
    113         super(context, attrs);
    114 
    115         TypedArray a = context.obtainStyledAttributes(attrs,
    116                 com.android.internal.R.styleable.GridLayoutAnimation);
    117 
    118         Animation.Description d = Animation.Description.parseValue(
    119                 a.peekValue(com.android.internal.R.styleable.GridLayoutAnimation_columnDelay));
    120         mColumnDelay = d.value;
    121         d = Animation.Description.parseValue(
    122                 a.peekValue(com.android.internal.R.styleable.GridLayoutAnimation_rowDelay));
    123         mRowDelay = d.value;
    124         //noinspection PointlessBitwiseExpression
    125         mDirection = a.getInt(com.android.internal.R.styleable.GridLayoutAnimation_direction,
    126                 DIRECTION_LEFT_TO_RIGHT | DIRECTION_TOP_TO_BOTTOM);
    127         mDirectionPriority = a.getInt(com.android.internal.R.styleable.GridLayoutAnimation_directionPriority,
    128                 PRIORITY_NONE);
    129 
    130         a.recycle();
    131     }
    132 
    133     /**
    134      * Creates a new layout animation controller with a delay of 50%
    135      * for both rows and columns and the specified animation.
    136      *
    137      * @param animation the animation to use on each child of the view group
    138      */
    139     public GridLayoutAnimationController(Animation animation) {
    140         this(animation, 0.5f, 0.5f);
    141     }
    142 
    143     /**
    144      * Creates a new layout animation controller with the specified delays
    145      * and the specified animation.
    146      *
    147      * @param animation the animation to use on each child of the view group
    148      * @param columnDelay the delay by which each column animation must be offset
    149      * @param rowDelay the delay by which each row animation must be offset
    150      */
    151     public GridLayoutAnimationController(Animation animation, float columnDelay, float rowDelay) {
    152         super(animation);
    153         mColumnDelay = columnDelay;
    154         mRowDelay = rowDelay;
    155     }
    156 
    157     /**
    158      * Returns the delay by which the children's animation are offset from one
    159      * column to the other. The delay is expressed as a fraction of the
    160      * animation duration.
    161      *
    162      * @return a fraction of the animation duration
    163      *
    164      * @see #setColumnDelay(float)
    165      * @see #getRowDelay()
    166      * @see #setRowDelay(float)
    167      */
    168     public float getColumnDelay() {
    169         return mColumnDelay;
    170     }
    171 
    172     /**
    173      * Sets the delay, as a fraction of the animation duration, by which the
    174      * children's animations are offset from one column to the other.
    175      *
    176      * @param columnDelay a fraction of the animation duration
    177      *
    178      * @see #getColumnDelay()
    179      * @see #getRowDelay()
    180      * @see #setRowDelay(float)
    181      */
    182     public void setColumnDelay(float columnDelay) {
    183         mColumnDelay = columnDelay;
    184     }
    185 
    186     /**
    187      * Returns the delay by which the children's animation are offset from one
    188      * row to the other. The delay is expressed as a fraction of the
    189      * animation duration.
    190      *
    191      * @return a fraction of the animation duration
    192      *
    193      * @see #setRowDelay(float)
    194      * @see #getColumnDelay()
    195      * @see #setColumnDelay(float)
    196      */
    197     public float getRowDelay() {
    198         return mRowDelay;
    199     }
    200 
    201     /**
    202      * Sets the delay, as a fraction of the animation duration, by which the
    203      * children's animations are offset from one row to the other.
    204      *
    205      * @param rowDelay a fraction of the animation duration
    206      *
    207      * @see #getRowDelay()
    208      * @see #getColumnDelay()
    209      * @see #setColumnDelay(float)
    210      */
    211     public void setRowDelay(float rowDelay) {
    212         mRowDelay = rowDelay;
    213     }
    214 
    215     /**
    216      * Returns the direction of the animation. {@link #DIRECTION_HORIZONTAL_MASK}
    217      * and {@link #DIRECTION_VERTICAL_MASK} can be used to retrieve the
    218      * horizontal and vertical components of the direction.
    219      *
    220      * @return the direction of the animation
    221      *
    222      * @see #setDirection(int)
    223      * @see #DIRECTION_BOTTOM_TO_TOP
    224      * @see #DIRECTION_TOP_TO_BOTTOM
    225      * @see #DIRECTION_LEFT_TO_RIGHT
    226      * @see #DIRECTION_RIGHT_TO_LEFT
    227      * @see #DIRECTION_HORIZONTAL_MASK
    228      * @see #DIRECTION_VERTICAL_MASK
    229      */
    230     public int getDirection() {
    231         return mDirection;
    232     }
    233 
    234     /**
    235      * Sets the direction of the animation. The direction is expressed as an
    236      * integer containing a horizontal and vertical component. For instance,
    237      * <code>DIRECTION_BOTTOM_TO_TOP | DIRECTION_RIGHT_TO_LEFT</code>.
    238      *
    239      * @param direction the direction of the animation
    240      *
    241      * @see #getDirection()
    242      * @see #DIRECTION_BOTTOM_TO_TOP
    243      * @see #DIRECTION_TOP_TO_BOTTOM
    244      * @see #DIRECTION_LEFT_TO_RIGHT
    245      * @see #DIRECTION_RIGHT_TO_LEFT
    246      * @see #DIRECTION_HORIZONTAL_MASK
    247      * @see #DIRECTION_VERTICAL_MASK
    248      */
    249     public void setDirection(int direction) {
    250         mDirection = direction;
    251     }
    252 
    253     /**
    254      * Returns the direction priority for the animation. The priority can
    255      * be either {@link #PRIORITY_NONE}, {@link #PRIORITY_COLUMN} or
    256      * {@link #PRIORITY_ROW}.
    257      *
    258      * @return the priority of the animation direction
    259      *
    260      * @see #setDirectionPriority(int)
    261      * @see #PRIORITY_COLUMN
    262      * @see #PRIORITY_NONE
    263      * @see #PRIORITY_ROW
    264      */
    265     public int getDirectionPriority() {
    266         return mDirectionPriority;
    267     }
    268 
    269     /**
    270      * Specifies the direction priority of the animation. For instance,
    271      * {@link #PRIORITY_COLUMN} will give priority to columns: the animation
    272      * will first play on the column, then on the rows.Z
    273      *
    274      * @param directionPriority the direction priority of the animation
    275      *
    276      * @see #getDirectionPriority()
    277      * @see #PRIORITY_COLUMN
    278      * @see #PRIORITY_NONE
    279      * @see #PRIORITY_ROW
    280      */
    281     public void setDirectionPriority(int directionPriority) {
    282         mDirectionPriority = directionPriority;
    283     }
    284 
    285     /**
    286      * {@inheritDoc}
    287      */
    288     @Override
    289     public boolean willOverlap() {
    290         return mColumnDelay < 1.0f || mRowDelay < 1.0f;
    291     }
    292 
    293     /**
    294      * {@inheritDoc}
    295      */
    296     @Override
    297     protected long getDelayForView(View view) {
    298         ViewGroup.LayoutParams lp = view.getLayoutParams();
    299         AnimationParameters params = (AnimationParameters) lp.layoutAnimationParameters;
    300 
    301         if (params == null) {
    302             return 0;
    303         }
    304 
    305         final int column = getTransformedColumnIndex(params);
    306         final int row = getTransformedRowIndex(params);
    307 
    308         final int rowsCount = params.rowsCount;
    309         final int columnsCount = params.columnsCount;
    310 
    311         final long duration = mAnimation.getDuration();
    312         final float columnDelay = mColumnDelay * duration;
    313         final float rowDelay = mRowDelay * duration;
    314 
    315         float totalDelay;
    316         long viewDelay;
    317 
    318         if (mInterpolator == null) {
    319             mInterpolator = new LinearInterpolator();
    320         }
    321 
    322         switch (mDirectionPriority) {
    323             case PRIORITY_COLUMN:
    324                 viewDelay = (long) (row * rowDelay + column * rowsCount * rowDelay);
    325                 totalDelay = rowsCount * rowDelay + columnsCount * rowsCount * rowDelay;
    326                 break;
    327             case PRIORITY_ROW:
    328                 viewDelay = (long) (column * columnDelay + row * columnsCount * columnDelay);
    329                 totalDelay = columnsCount * columnDelay + rowsCount * columnsCount * columnDelay;
    330                 break;
    331             case PRIORITY_NONE:
    332             default:
    333                 viewDelay = (long) (column * columnDelay + row * rowDelay);
    334                 totalDelay = columnsCount * columnDelay + rowsCount * rowDelay;
    335                 break;
    336         }
    337 
    338         float normalizedDelay = viewDelay / totalDelay;
    339         normalizedDelay = mInterpolator.getInterpolation(normalizedDelay);
    340 
    341         return (long) (normalizedDelay * totalDelay);
    342     }
    343 
    344     private int getTransformedColumnIndex(AnimationParameters params) {
    345         int index;
    346         switch (getOrder()) {
    347             case ORDER_REVERSE:
    348                 index = params.columnsCount - 1 - params.column;
    349                 break;
    350             case ORDER_RANDOM:
    351                 if (mRandomizer == null) {
    352                     mRandomizer = new Random();
    353                 }
    354                 index = (int) (params.columnsCount * mRandomizer.nextFloat());
    355                 break;
    356             case ORDER_NORMAL:
    357             default:
    358                 index = params.column;
    359                 break;
    360         }
    361 
    362         int direction = mDirection & DIRECTION_HORIZONTAL_MASK;
    363         if (direction == DIRECTION_RIGHT_TO_LEFT) {
    364             index = params.columnsCount - 1 - index;
    365         }
    366 
    367         return index;
    368     }
    369 
    370     private int getTransformedRowIndex(AnimationParameters params) {
    371         int index;
    372         switch (getOrder()) {
    373             case ORDER_REVERSE:
    374                 index = params.rowsCount - 1 - params.row;
    375                 break;
    376             case ORDER_RANDOM:
    377                 if (mRandomizer == null) {
    378                     mRandomizer = new Random();
    379                 }
    380                 index = (int) (params.rowsCount * mRandomizer.nextFloat());
    381                 break;
    382             case ORDER_NORMAL:
    383             default:
    384                 index = params.row;
    385                 break;
    386         }
    387 
    388         int direction = mDirection & DIRECTION_VERTICAL_MASK;
    389         if (direction == DIRECTION_BOTTOM_TO_TOP) {
    390             index = params.rowsCount - 1 - index;
    391         }
    392 
    393         return index;
    394     }
    395 
    396     /**
    397      * The set of parameters that has to be attached to each view contained in
    398      * the view group animated by the grid layout animation controller. These
    399      * parameters are used to compute the start time of each individual view's
    400      * animation.
    401      */
    402     public static class AnimationParameters extends
    403             LayoutAnimationController.AnimationParameters {
    404         /**
    405          * The view group's column to which the view belongs.
    406          */
    407         public int column;
    408 
    409         /**
    410          * The view group's row to which the view belongs.
    411          */
    412         public int row;
    413 
    414         /**
    415          * The number of columns in the view's enclosing grid layout.
    416          */
    417         public int columnsCount;
    418 
    419         /**
    420          * The number of rows in the view's enclosing grid layout.
    421          */
    422         public int rowsCount;
    423     }
    424 }
    425