• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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      */
GridLayoutAnimationController(Context context, AttributeSet attrs)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      */
GridLayoutAnimationController(Animation animation)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      */
GridLayoutAnimationController(Animation animation, float columnDelay, float rowDelay)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      */
getColumnDelay()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      */
setColumnDelay(float columnDelay)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      */
getRowDelay()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      */
setRowDelay(float rowDelay)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      */
getDirection()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      */
setDirection(int direction)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      */
getDirectionPriority()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      */
setDirectionPriority(int directionPriority)281     public void setDirectionPriority(int directionPriority) {
282         mDirectionPriority = directionPriority;
283     }
284 
285     /**
286      * {@inheritDoc}
287      */
288     @Override
willOverlap()289     public boolean willOverlap() {
290         return mColumnDelay < 1.0f || mRowDelay < 1.0f;
291     }
292 
293     /**
294      * {@inheritDoc}
295      */
296     @Override
getDelayForView(View view)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 
getTransformedColumnIndex(AnimationParameters params)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 
getTransformedRowIndex(AnimationParameters params)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