ViewGroup.java revision ec25df9fbc685be384f8dd764fa224a4d923e9d8
1b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch/*
2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * Copyright (C) 2006 The Android Open Source Project
3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *
4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * Licensed under the Apache License, Version 2.0 (the "License");
5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * you may not use this file except in compliance with the License.
6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * You may obtain a copy of the License at
7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *
8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *      http://www.apache.org/licenses/LICENSE-2.0
9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *
10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * Unless required by applicable law or agreed to in writing, software
11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * distributed under the License is distributed on an "AS IS" BASIS,
12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * See the License for the specific language governing permissions and
14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * limitations under the License.
15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block */
16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockpackage android.view;
18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockimport com.android.internal.R;
20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockimport android.content.Context;
22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockimport android.content.res.TypedArray;
23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockimport android.graphics.Bitmap;
24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockimport android.graphics.Canvas;
25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockimport android.graphics.Paint;
26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockimport android.graphics.Rect;
27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockimport android.graphics.RectF;
28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockimport android.graphics.Region;
29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockimport android.os.Parcelable;
303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochimport android.os.SystemClock;
31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockimport android.util.AttributeSet;
32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockimport android.util.Config;
33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockimport android.util.EventLog;
34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockimport android.util.Log;
35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockimport android.util.SparseArray;
36e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochimport android.view.accessibility.AccessibilityEvent;
37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockimport android.view.animation.Animation;
38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockimport android.view.animation.AnimationUtils;
39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockimport android.view.animation.LayoutAnimationController;
40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockimport android.view.animation.Transformation;
41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockimport java.util.ArrayList;
43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block/**
45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * <p>
46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * A <code>ViewGroup</code> is a special view that can contain other views
47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * (called children.) The view group is the base class for layouts and views
48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * containers. This class also defines the
49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * {@link android.view.ViewGroup.LayoutParams} class which serves as the base
50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * class for layouts parameters.
51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * </p>
52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *
53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * <p>
54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * Also see {@link LayoutParams} for layout attributes.
55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * </p>
56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *
57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * @attr ref android.R.styleable#ViewGroup_clipChildren
58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * @attr ref android.R.styleable#ViewGroup_clipToPadding
59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * @attr ref android.R.styleable#ViewGroup_layoutAnimation
60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * @attr ref android.R.styleable#ViewGroup_animationCache
61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * @attr ref android.R.styleable#ViewGroup_persistentDrawingCache
62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * @attr ref android.R.styleable#ViewGroup_alwaysDrawnWithCache
63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * @attr ref android.R.styleable#ViewGroup_addStatesFromChildren
64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * @attr ref android.R.styleable#ViewGroup_descendantFocusability
65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block */
66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockpublic abstract class ViewGroup extends View implements ViewParent, ViewManager {
67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    private static final boolean DBG = false;
68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    /**
70257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch     * Views which have been hidden or removed which need to be animated on
71257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch     * their way out.
72257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch     * This field should be made private, so it is hidden from the SDK.
73257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch     * {@hide}
74257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch     */
75257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    protected ArrayList<View> mDisappearingChildren;
76257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
77257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    /**
78257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch     * Listener used to propagate events indicating when children are added
79257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch     * and/or removed from a view group.
80257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch     * This field should be made private, so it is hidden from the SDK.
81257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch     * {@hide}
82257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch     */
83257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    protected OnHierarchyChangeListener mOnHierarchyChangeListener;
84257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
85257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // The view contained within this ViewGroup that has or contains focus.
86257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    private View mFocused;
87257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
88257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // The current transformation to apply on the child being drawn
89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    private Transformation mChildTransformation;
90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    private RectF mInvalidateRegion;
91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Target of Motion events
93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    private View mMotionTarget;
94e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    private final Rect mTempRect = new Rect();
95e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
96e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // Layout animation
97e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    private LayoutAnimationController mLayoutAnimationController;
98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    private Animation.AnimationListener mAnimationListener;
99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    /**
101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * Internal flags.
102e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke     *
103e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke     * This field should be made private, so it is hidden from the SDK.
104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * {@hide}
105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     */
106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    protected int mGroupFlags;
107e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // When set, ViewGroup invalidates only the child's rectangle
109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Set by default
110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    private static final int FLAG_CLIP_CHILDREN = 0x1;
111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // When set, ViewGroup excludes the padding area from the invalidate rectangle
113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Set by default
114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    private static final int FLAG_CLIP_TO_PADDING = 0x2;
115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // When set, dispatchDraw() will invoke invalidate(); this is set by drawChild() when
117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // a child needs to be invalidated and FLAG_OPTIMIZE_INVALIDATE is set
118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    private static final int FLAG_INVALIDATE_REQUIRED  = 0x4;
119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // When set, dispatchDraw() will run the layout animation and unset the flag
121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    private static final int FLAG_RUN_ANIMATION = 0x8;
122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // When set, there is either no layout animation on the ViewGroup or the layout
124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // animation is over
125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Set by default
126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    private static final int FLAG_ANIMATION_DONE = 0x10;
127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // If set, this ViewGroup has padding; if unset there is no padding and we don't need
129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // to clip it, even if FLAG_CLIP_TO_PADDING is set
130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    private static final int FLAG_PADDING_NOT_NULL = 0x20;
131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
132257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // When set, this ViewGroup caches its children in a Bitmap before starting a layout animation
133257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // Set by default
134257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    private static final int FLAG_ANIMATION_CACHE = 0x40;
135257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
136257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // When set, this ViewGroup converts calls to invalidate(Rect) to invalidate() during a
137257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    // layout animation; this avoid clobbering the hierarchy
138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Automatically set when the layout animation starts, depending on the animation's
139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // characteristics
140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    private static final int FLAG_OPTIMIZE_INVALIDATE = 0x80;
141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // When set, the next call to drawChild() will clear mChildTransformation's matrix
143b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    private static final int FLAG_CLEAR_TRANSFORMATION = 0x100;
144b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // When set, this ViewGroup invokes mAnimationListener.onAnimationEnd() and removes
146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // the children's Bitmap caches if necessary
147e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // This flag is set when the layout animation is over (after FLAG_ANIMATION_DONE is set)
148e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    private static final int FLAG_NOTIFY_ANIMATION_LISTENER = 0x200;
149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
150d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    /**
151d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block     * When set, the drawing method will call {@link #getChildDrawingOrder(int, int)}
152b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch     * to get the index of the child to draw for that iteration.
153d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block     */
154d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    protected static final int FLAG_USE_CHILD_DRAWING_ORDER = 0x400;
155257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
156257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    /**
157d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block     * When set, this ViewGroup supports static transformations on children; this causes
158086aeeaae12517475c22695a200be45495516549Ben Murdoch     * {@link #getChildStaticTransformation(View, android.view.animation.Transformation)} to be
159086aeeaae12517475c22695a200be45495516549Ben Murdoch     * invoked when a child is drawn.
160086aeeaae12517475c22695a200be45495516549Ben Murdoch     *
161086aeeaae12517475c22695a200be45495516549Ben Murdoch     * Any subclass overriding
162086aeeaae12517475c22695a200be45495516549Ben Murdoch     * {@link #getChildStaticTransformation(View, android.view.animation.Transformation)} should
163b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch     * set this flags in {@link #mGroupFlags}.
164e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch     *
165b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch     * {@hide}
166b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch     */
167b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    protected static final int FLAG_SUPPORT_STATIC_TRANSFORMATIONS = 0x800;
168b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
169086aeeaae12517475c22695a200be45495516549Ben Murdoch    // When the previous drawChild() invocation used an alpha value that was lower than
170086aeeaae12517475c22695a200be45495516549Ben Murdoch    // 1.0 and set it in mCachePaint
171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    private static final int FLAG_ALPHA_LOWER_THAN_ONE = 0x1000;
172e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
173b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    /**
174b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch     * When set, this ViewGroup's drawable states also include those
17569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch     * of its children.
17669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch     */
17769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    private static final int FLAG_ADD_STATES_FROM_CHILDREN = 0x2000;
17869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
17969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    /**
18069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch     * When set, this ViewGroup tries to always draw its children using their drawing cache.
181b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch     */
182086aeeaae12517475c22695a200be45495516549Ben Murdoch    private static final int FLAG_ALWAYS_DRAWN_WITH_CACHE = 0x4000;
183e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
184e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    /**
185e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch     * When set, and if FLAG_ALWAYS_DRAWN_WITH_CACHE is not set, this ViewGroup will try to
186e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch     * draw its children with their drawing cache.
187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     */
1881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    private static final int FLAG_CHILDREN_DRAWN_WITH_CACHE = 0x8000;
1891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    /**
191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * When set, this group will go through its list of children to notify them of
192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * any drawable state change.
193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     */
194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    private static final int FLAG_NOTIFY_CHILDREN_ON_DRAWABLE_STATE_CHANGE = 0x10000;
195b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
196e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    private static final int FLAG_MASK_FOCUSABILITY = 0x60000;
197b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
198b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    /**
199b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch     * This view will get focus before any of its descendants.
200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     */
201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    public static final int FOCUS_BEFORE_DESCENDANTS = 0x20000;
202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    /**
2043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch     * This view will get focus only if none of its descendants want it.
205e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke     */
206e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    public static final int FOCUS_AFTER_DESCENDANTS = 0x40000;
2073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    /**
2093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch     * This view will block any of its descendants from getting focus, even
210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * if they are focusable.
2113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch     */
212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    public static final int FOCUS_BLOCK_DESCENDANTS = 0x60000;
213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    /**
215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * Used to map between enum in attrubutes and flag values.
216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     */
217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    private static final int[] DESCENDANT_FOCUSABILITY_FLAGS =
218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            {FOCUS_BEFORE_DESCENDANTS, FOCUS_AFTER_DESCENDANTS,
219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    FOCUS_BLOCK_DESCENDANTS};
220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    /**
222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * When set, this ViewGroup should not intercept touch events.
223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     */
224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    private static final int FLAG_DISALLOW_INTERCEPT = 0x80000;
225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    /**
227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * Indicates which types of drawing caches are to be kept in memory.
228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * This field should be made private, so it is hidden from the SDK.
229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * {@hide}
230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     */
231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    protected int mPersistentDrawingCache;
232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    /**
234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * Used to indicate that no drawing cache should be kept in memory.
235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     */
236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    public static final int PERSISTENT_NO_CACHE = 0x0;
237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    /**
239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * Used to indicate that the animation drawing cache should be kept in memory.
240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     */
241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    public static final int PERSISTENT_ANIMATION_CACHE = 0x1;
242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    /**
244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * Used to indicate that the scrolling drawing cache should be kept in memory.
245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     */
246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    public static final int PERSISTENT_SCROLLING_CACHE = 0x2;
247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    /**
249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * Used to indicate that all drawing caches should be kept in memory.
250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     */
251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    public static final int PERSISTENT_ALL_CACHES = 0x3;
252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    /**
254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * We clip to padding when FLAG_CLIP_TO_PADDING and FLAG_PADDING_NOT_NULL
255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * are set at the same time.
256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     */
257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    protected static final int CLIP_TO_PADDING_MASK = FLAG_CLIP_TO_PADDING | FLAG_PADDING_NOT_NULL;
258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Index of the child's left position in the mLocation array
260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    private static final int CHILD_LEFT_INDEX = 0;
261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Index of the child's top position in the mLocation array
262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    private static final int CHILD_TOP_INDEX = 1;
263e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Child views of this ViewGroup
265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    private View[] mChildren;
266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Number of valid children in the mChildren array, the rest should be null or not
267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // considered as children
268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    private int mChildrenCount;
269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    private static final int ARRAY_INITIAL_CAPACITY = 12;
271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    private static final int ARRAY_CAPACITY_INCREMENT = 12;
272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Used to draw cached views
274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    private final Paint mCachePaint = new Paint();
275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    public ViewGroup(Context context) {
277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        super(context);
278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        initViewGroup();
279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    public ViewGroup(Context context, AttributeSet attrs) {
282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        super(context, attrs);
283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        initViewGroup();
284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        initFromAttributes(context, attrs);
285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    public ViewGroup(Context context, AttributeSet attrs, int defStyle) {
288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        super(context, attrs, defStyle);
289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        initViewGroup();
290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        initFromAttributes(context, attrs);
291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    private void initViewGroup() {
294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // ViewGroup doesn't draw by default
295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        setFlags(WILL_NOT_DRAW, DRAW_MASK);
296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        mGroupFlags |= FLAG_CLIP_CHILDREN;
297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        mGroupFlags |= FLAG_CLIP_TO_PADDING;
298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        mGroupFlags |= FLAG_ANIMATION_DONE;
299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        mGroupFlags |= FLAG_ANIMATION_CACHE;
300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        mGroupFlags |= FLAG_ALWAYS_DRAWN_WITH_CACHE;
301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        setDescendantFocusability(FOCUS_BEFORE_DESCENDANTS);
303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        mChildren = new View[ARRAY_INITIAL_CAPACITY];
305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        mChildrenCount = 0;
306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        mCachePaint.setDither(false);
308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        mPersistentDrawingCache = PERSISTENT_SCROLLING_CACHE;
310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    private void initFromAttributes(Context context, AttributeSet attrs) {
313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        TypedArray a = context.obtainStyledAttributes(attrs,
314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                R.styleable.ViewGroup);
315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        final int N = a.getIndexCount();
317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        for (int i = 0; i < N; i++) {
318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            int attr = a.getIndex(i);
319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            switch (attr) {
320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                case R.styleable.ViewGroup_clipChildren:
321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    setClipChildren(a.getBoolean(attr, true));
322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    break;
323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                case R.styleable.ViewGroup_clipToPadding:
324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    setClipToPadding(a.getBoolean(attr, true));
325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    break;
326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                case R.styleable.ViewGroup_animationCache:
327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    setAnimationCacheEnabled(a.getBoolean(attr, true));
328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    break;
329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                case R.styleable.ViewGroup_persistentDrawingCache:
330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    setPersistentDrawingCache(a.getInt(attr, PERSISTENT_SCROLLING_CACHE));
3313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                    break;
332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                case R.styleable.ViewGroup_addStatesFromChildren:
3333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                    setAddStatesFromChildren(a.getBoolean(attr, false));
334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    break;
335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                case R.styleable.ViewGroup_alwaysDrawnWithCache:
336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    setAlwaysDrawnWithCacheEnabled(a.getBoolean(attr, true));
337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    break;
338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                case R.styleable.ViewGroup_layoutAnimation:
339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    int id = a.getResourceId(attr, -1);
340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    if (id > 0) {
341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        setLayoutAnimation(AnimationUtils.loadLayoutAnimation(mContext, id));
342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    }
343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    break;
344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                case R.styleable.ViewGroup_descendantFocusability:
345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    setDescendantFocusability(DESCENDANT_FOCUSABILITY_FLAGS[a.getInt(attr, 0)]);
346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    break;
347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            }
348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        a.recycle();
351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    /**
354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * Gets the descendant focusability of this view group.  The descendant
355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * focusability defines the relationship between this view group and its
356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * descendants when looking for a view to take focus in
357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * {@link #requestFocus(int, android.graphics.Rect)}.
358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     *
359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * @return one of {@link #FOCUS_BEFORE_DESCENDANTS}, {@link #FOCUS_AFTER_DESCENDANTS},
360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     *   {@link #FOCUS_BLOCK_DESCENDANTS}.
361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     */
362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    @ViewDebug.ExportedProperty(mapping = {
363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        @ViewDebug.IntToString(from = FOCUS_BEFORE_DESCENDANTS, to = "FOCUS_BEFORE_DESCENDANTS"),
364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        @ViewDebug.IntToString(from = FOCUS_AFTER_DESCENDANTS, to = "FOCUS_AFTER_DESCENDANTS"),
365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        @ViewDebug.IntToString(from = FOCUS_BLOCK_DESCENDANTS, to = "FOCUS_BLOCK_DESCENDANTS")
366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    })
367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    public int getDescendantFocusability() {
368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        return mGroupFlags & FLAG_MASK_FOCUSABILITY;
369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    /**
372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * Set the descendant focusability of this view group. This defines the relationship
373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * between this view group and its descendants when looking for a view to
374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * take focus in {@link #requestFocus(int, android.graphics.Rect)}.
375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     *
376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * @param focusability one of {@link #FOCUS_BEFORE_DESCENDANTS}, {@link #FOCUS_AFTER_DESCENDANTS},
377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     *   {@link #FOCUS_BLOCK_DESCENDANTS}.
378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     */
379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    public void setDescendantFocusability(int focusability) {
380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        switch (focusability) {
381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case FOCUS_BEFORE_DESCENDANTS:
3823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            case FOCUS_AFTER_DESCENDANTS:
3833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            case FOCUS_BLOCK_DESCENDANTS:
3843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                break;
3853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            default:
3863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                throw new IllegalArgumentException("must be one of FOCUS_BEFORE_DESCENDANTS, "
3873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        + "FOCUS_AFTER_DESCENDANTS, FOCUS_BLOCK_DESCENDANTS");
3883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
3893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        mGroupFlags &= ~FLAG_MASK_FOCUSABILITY;
3903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        mGroupFlags |= (focusability & FLAG_MASK_FOCUSABILITY);
3913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
3923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    /**
3943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch     * {@inheritDoc}
3953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch     */
3963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    @Override
3973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    void handleFocusGainInternal(int direction, Rect previouslyFocusedRect) {
398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (mFocused != null) {
399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            mFocused.unFocus();
400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            mFocused = null;
401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
4023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        super.handleFocusGainInternal(direction, previouslyFocusedRect);
4033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
4043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    /**
4063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch     * {@inheritDoc}
407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     */
408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    public void requestChildFocus(View child, View focused) {
409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (DBG) {
410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            System.out.println(this + " requestChildFocus()");
411257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        }
412257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        if (getDescendantFocusability() == FOCUS_BLOCK_DESCENDANTS) {
413257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            return;
414257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        }
415257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
416e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        // Unfocus us, if necessary
417e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        super.unFocus();
418e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
419b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        // We had a previous notion of who had focus. Clear it.
420e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        if (mFocused != child) {
4218a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang            if (mFocused != null) {
4228a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                mFocused.unFocus();
423b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            }
4248a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
425b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            mFocused = child;
426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (mParent != null) {
428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            mParent.requestChildFocus(this, focused);
429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
432257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    /**
433257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch     * {@inheritDoc}
434257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch     */
435257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    public void focusableViewAvailable(View v) {
436257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        if (mParent != null
437e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                // shortcut: don't report a new focusable view if we block our descendants from
438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                // getting focus
439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                && (getDescendantFocusability() != FOCUS_BLOCK_DESCENDANTS)
440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                // shortcut: don't report a new focusable view if we already are focused
441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                // (and we don't prefer our descendants)
442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                //
443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                // note: knowing that mFocused is non-null is not a good enough reason
444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                // to break the traversal since in that case we'd actually have to find
445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                // the focused view and make sure it wasn't FOCUS_AFTER_DESCENDANTS and
446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                // an ancestor of v; this will get checked for at ViewRoot
447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                && !(isFocused() && getDescendantFocusability() != FOCUS_AFTER_DESCENDANTS)) {
448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            mParent.focusableViewAvailable(v);
449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    /**
453257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch     * {@inheritDoc}
454257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch     */
455257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    public boolean showContextMenuForChild(View originalView) {
456257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        return mParent != null && mParent.showContextMenuForChild(originalView);
457257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
458e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    /**
460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * Find the nearest view in the specified direction that wants to take
461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * focus.
462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     *
463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * @param focused The view that currently has focus
464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and
465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     *        FOCUS_RIGHT, or 0 for not applicable.
466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     */
467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    public View focusSearch(View focused, int direction) {
468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (isRootNamespace()) {
469257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            // root namespace means we should consider ourselves the top of the
470257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            // tree for focus searching; otherwise we could be focus searching
471257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            // into other tabs.  see LocalActivityManager and TabHost for more info
472257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            return FocusFinder.getInstance().findNextFocus(this, focused, direction);
473257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        } else if (mParent != null) {
474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            return mParent.focusSearch(focused, direction);
475e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        }
476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        return null;
477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    /**
480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * {@inheritDoc}
481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     */
482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    public boolean requestChildRectangleOnScreen(View child, Rect rectangle, boolean immediate) {
483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        return false;
484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    /**
487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * {@inheritDoc}
488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     */
489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    @Override
490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    public boolean dispatchUnhandledMove(View focused, int direction) {
491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        return mFocused != null &&
492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                mFocused.dispatchUnhandledMove(focused, direction);
493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    /**
496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * {@inheritDoc}
497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     */
498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    public void clearChildFocus(View child) {
4993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (DBG) {
500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            System.out.println(this + " clearChildFocus()");
501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        mFocused = null;
5043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (mParent != null) {
505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            mParent.clearChildFocus(this);
506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    /**
510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * {@inheritDoc}
511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     */
512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    @Override
513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    public void clearFocus() {
514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        super.clearFocus();
515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // clear any child focus if it exists
517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (mFocused != null) {
518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            mFocused.clearFocus();
519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    /**
523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * {@inheritDoc}
524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     */
525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    @Override
526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    void unFocus() {
527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (DBG) {
528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            System.out.println(this + " unFocus()");
529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
530257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
531257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        super.unFocus();
532257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        if (mFocused != null) {
533257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            mFocused.unFocus();
534257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        }
535e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        mFocused = null;
536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    /**
539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * Returns the focused child of this view, if any. The child may have focus
540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * or contain focus.
541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     *
542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * @return the focused child or null.
543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     */
544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    public View getFocusedChild() {
545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        return mFocused;
546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    /**
549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * Returns true if this view has or contains focus
550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     *
551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * @return true if this view has or contains focus
552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     */
553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    @Override
554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    public boolean hasFocus() {
555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        return (mPrivateFlags & FOCUSED) != 0 || mFocused != null;
556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    /*
559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * (non-Javadoc)
560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     *
561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * @see android.view.View#findFocus()
562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     */
563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    @Override
564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    public View findFocus() {
565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (DBG) {
566257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            System.out.println("Find focus in " + this + ": flags="
567257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                    + isFocused() + ", child=" + mFocused);
568257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        }
569257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
570257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        if (isFocused()) {
571e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            return this;
572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (mFocused != null) {
575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            return mFocused.findFocus();
576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        return null;
578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    /**
581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * {@inheritDoc}
5823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch     */
583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    @Override
5843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    public boolean hasFocusable() {
585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            return false;
587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (isFocusable()) {
590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            return true;
591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
593257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        final int descendantFocusability = getDescendantFocusability();
594257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        if (descendantFocusability != FOCUS_BLOCK_DESCENDANTS) {
595257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            final int count = mChildrenCount;
596257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            final View[] children = mChildren;
597257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
598e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke            for (int i = 0; i < count; i++) {
599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                final View child = children[i];
600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                if (child.hasFocusable()) {
6013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                    return true;
602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                }
6033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            }
604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
6053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        return false;
607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    /**
610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * {@inheritDoc}
611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     */
612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    @Override
613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    public void addFocusables(ArrayList<View> views, int direction) {
614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        addFocusables(views, direction, FOCUSABLES_TOUCH_MODE);
615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    /**
618257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch     * {@inheritDoc}
619257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch     */
620257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    @Override
621257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    public void addFocusables(ArrayList<View> views, int direction, int focusableMode) {
622257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        final int focusableCount = views.size();
623e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        final int descendantFocusability = getDescendantFocusability();
625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (descendantFocusability != FOCUS_BLOCK_DESCENDANTS) {
627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            final int count = mChildrenCount;
628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            final View[] children = mChildren;
629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            for (int i = 0; i < count; i++) {
631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                final View child = children[i];
632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE) {
633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    child.addFocusables(views, direction, focusableMode);
634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                }
635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            }
636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // we add ourselves (if focusable) in all cases except for when we are
639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // FOCUS_AFTER_DESCENDANTS and there are some descendants focusable.  this is
640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // to avoid the focus search finding layouts when a more precise search
641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // among the focusable children would be more interesting.
642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (
643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            descendantFocusability != FOCUS_AFTER_DESCENDANTS ||
644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                // No focusable descendants
645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                (focusableCount == views.size())) {
646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            super.addFocusables(views, direction, focusableMode);
6473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        }
6483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
6493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    /**
651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * {@inheritDoc}
652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     */
653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    @Override
654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    public void dispatchWindowFocusChanged(boolean hasFocus) {
655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        super.dispatchWindowFocusChanged(hasFocus);
656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        final int count = mChildrenCount;
657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        final View[] children = mChildren;
658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        for (int i = 0; i < count; i++) {
659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            children[i].dispatchWindowFocusChanged(hasFocus);
660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
662257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
663257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    /**
664257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch     * {@inheritDoc}
665257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch     */
666257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    @Override
667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    public void addTouchables(ArrayList<View> views) {
668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        super.addTouchables(views);
669e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        final int count = mChildrenCount;
671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        final View[] children = mChildren;
672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        for (int i = 0; i < count; i++) {
674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            final View child = children[i];
675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE) {
676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                child.addTouchables(views);
677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            }
678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
679402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    }
6801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
6811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    /**
682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * {@inheritDoc}
683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     */
684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    @Override
6851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    public void dispatchWindowVisibilityChanged(int visibility) {
6861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        super.dispatchWindowVisibilityChanged(visibility);
6871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        final int count = mChildrenCount;
688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        final View[] children = mChildren;
689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        for (int i = 0; i < count; i++) {
690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            children[i].dispatchWindowVisibilityChanged(visibility);
691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    /**
695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * {@inheritDoc}
696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     */
697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    public void recomputeViewAttributes(View child) {
698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        ViewParent parent = mParent;
699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (parent != null) parent.recomputeViewAttributes(this);
700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    @Override
703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    void dispatchCollectViewAttributes(int visibility) {
704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        visibility |= mViewFlags&VISIBILITY_MASK;
705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        super.dispatchCollectViewAttributes(visibility);
706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        final int count = mChildrenCount;
707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        final View[] children = mChildren;
708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        for (int i = 0; i < count; i++) {
709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            children[i].dispatchCollectViewAttributes(visibility);
710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    /**
714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * {@inheritDoc}
715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     */
716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    public void bringChildToFront(View child) {
717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        int index = indexOfChild(child);
718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (index >= 0) {
719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            removeFromArray(index);
720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            addInArray(child, mChildrenCount);
721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            child.mParent = this;
722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    /**
726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * {@inheritDoc}
727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     */
728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    @Override
729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    public boolean dispatchKeyEventPreIme(KeyEvent event) {
730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if ((mPrivateFlags & (FOCUSED | HAS_BOUNDS)) == (FOCUSED | HAS_BOUNDS)) {
731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            return super.dispatchKeyEventPreIme(event);
732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else if (mFocused != null && (mFocused.mPrivateFlags & HAS_BOUNDS) == HAS_BOUNDS) {
733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            return mFocused.dispatchKeyEventPreIme(event);
734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        return false;
736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
738257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    /**
739257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch     * {@inheritDoc}
740257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch     */
741257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    @Override
742257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    public boolean dispatchKeyEvent(KeyEvent event) {
743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if ((mPrivateFlags & (FOCUSED | HAS_BOUNDS)) == (FOCUSED | HAS_BOUNDS)) {
744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            return super.dispatchKeyEvent(event);
745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else if (mFocused != null && (mFocused.mPrivateFlags & HAS_BOUNDS) == HAS_BOUNDS) {
746589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch            return mFocused.dispatchKeyEvent(event);
7476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        }
7486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        return false;
7496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
7506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
7516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    /**
7526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block     * {@inheritDoc}
7536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block     */
7546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    @Override
7556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    public boolean dispatchKeyShortcutEvent(KeyEvent event) {
7566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        if ((mPrivateFlags & (FOCUSED | HAS_BOUNDS)) == (FOCUSED | HAS_BOUNDS)) {
7576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            return super.dispatchKeyShortcutEvent(event);
75869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        } else if (mFocused != null && (mFocused.mPrivateFlags & HAS_BOUNDS) == HAS_BOUNDS) {
759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            return mFocused.dispatchKeyShortcutEvent(event);
7603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        return false;
762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
7636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
7646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    /**
7653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch     * {@inheritDoc}
7666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block     */
7676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    @Override
768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    public boolean dispatchTrackballEvent(MotionEvent event) {
7696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        if ((mPrivateFlags & (FOCUSED | HAS_BOUNDS)) == (FOCUSED | HAS_BOUNDS)) {
770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            return super.dispatchTrackballEvent(event);
771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else if (mFocused != null && (mFocused.mPrivateFlags & HAS_BOUNDS) == HAS_BOUNDS) {
7726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            return mFocused.dispatchTrackballEvent(event);
773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
7743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        return false;
775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
7763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    /**
778b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch     * {@inheritDoc}
779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     */
780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    @Override
781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    public boolean dispatchTouchEvent(MotionEvent ev) {
782b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        final int action = ev.getAction();
783b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        final float xf = ev.getX();
784b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        final float yf = ev.getY();
785b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        final float scrolledXFloat = xf + mScrollX;
786b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        final float scrolledYFloat = yf + mScrollY;
7873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        final Rect frame = mTempRect;
788b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
789b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0;
790b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
791b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        if (action == MotionEvent.ACTION_DOWN) {
792b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            if (mMotionTarget != null) {
793b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                // this is weird, we got a pen down, but we thought it was
7943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                // already down!
795b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                // XXX: We should probably send an ACTION_UP to the current
796b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                // target.
797b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                mMotionTarget = null;
798b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            }
799b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            // If we're disallowing intercept or if we're allowing and we didn't
800b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            // intercept
801b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            if (disallowIntercept || !onInterceptTouchEvent(ev)) {
802b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                // reset this event's action (just to protect ourselves)
8033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                ev.setAction(MotionEvent.ACTION_DOWN);
804b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                // We know we want to dispatch the event down, find a child
805b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                // who can handle it, start with the front-most child.
806b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                final int scrolledXInt = (int) scrolledXFloat;
807b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                final int scrolledYInt = (int) scrolledYFloat;
808b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                final View[] children = mChildren;
809b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                final int count = mChildrenCount;
810b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                for (int i = count - 1; i >= 0; i--) {
811b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                    final View child = children[i];
812b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                    if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE
813b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                            || child.getAnimation() != null) {
814b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                        child.getHitRect(frame);
815b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                        if (frame.contains(scrolledXInt, scrolledYInt)) {
816b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                            // offset the event to the view's coordinate system
817b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                            final float xc = scrolledXFloat - child.mLeft;
818b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                            final float yc = scrolledYFloat - child.mTop;
819b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                            ev.setLocation(xc, yc);
820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            if (child.dispatchTouchEvent(ev))  {
821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                // Event handled, we have a target now.
822b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                mMotionTarget = child;
823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                return true;
8243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                            }
825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            // The event didn't get handled, try the next view.
8265710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch                            // Don't reset the event's location, it's not
8275710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch                            // necessary here.
828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        }
829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    }
830b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                }
831b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            }
832b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        }
833b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
8343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        boolean isUpOrCancel = (action == MotionEvent.ACTION_UP) ||
835b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                (action == MotionEvent.ACTION_CANCEL);
8365710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch
8375710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch        if (isUpOrCancel) {
838b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            // Note, we've already copied the previous state to our local
8395710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch            // variable, so this takes effect on the next event
8405710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch            mGroupFlags &= ~FLAG_DISALLOW_INTERCEPT;
8415710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch        }
842b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
843b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        // The event wasn't an ACTION_DOWN, dispatch it to our target if
844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // we have one.
845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        final View target = mMotionTarget;
846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (target == null) {
847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            // We don't have a target, this means we're handling the
8483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            // event as a regular view.
849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            ev.setLocation(xf, yf);
850b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            return super.dispatchTouchEvent(ev);
851b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        }
852a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // if have a target, see if we're allowed to and want to intercept its
854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // events
855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (!disallowIntercept && onInterceptTouchEvent(ev)) {
856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            final float xc = scrolledXFloat - (float) target.mLeft;
857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            final float yc = scrolledYFloat - (float) target.mTop;
858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            ev.setAction(MotionEvent.ACTION_CANCEL);
859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            ev.setLocation(xc, yc);
860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            if (!target.dispatchTouchEvent(ev)) {
861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                // target didn't handle ACTION_CANCEL. not much we can do
862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                // but they should have.
863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            }
864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            // clear the target
865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            mMotionTarget = null;
866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            // Don't dispatch this event to our own view, because we already
867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            // saw it when intercepting; we just want to give the following
868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            // event to the normal onTouchEvent().
869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            return true;
870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (isUpOrCancel) {
873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            mMotionTarget = null;
874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // finally offset the event to the target's coordinate system and
877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // dispatch the event.
878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        final float xc = scrolledXFloat - (float) target.mLeft;
879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        final float yc = scrolledYFloat - (float) target.mTop;
8803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ev.setLocation(xc, yc);
881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        return target.dispatchTouchEvent(ev);
883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    /**
886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * {@inheritDoc}
887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     */
888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {
889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (disallowIntercept == ((mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0)) {
891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            // We're already in this state, assume our ancestors are too
892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            return;
893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (disallowIntercept) {
896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            mGroupFlags |= FLAG_DISALLOW_INTERCEPT;
897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {
898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            mGroupFlags &= ~FLAG_DISALLOW_INTERCEPT;
899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // Pass it up to our parent
902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (mParent != null) {
903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            mParent.requestDisallowInterceptTouchEvent(disallowIntercept);
904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    /**
9083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch     * Implement this method to intercept all touch screen motion events.  This
909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * allows you to watch events as they are dispatched to your children, and
9103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch     * take ownership of the current gesture at any point.
911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     *
912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * <p>Using this function takes some care, as it has a fairly complicated
913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * interaction with {@link View#onTouchEvent(MotionEvent)
914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * View.onTouchEvent(MotionEvent)}, and using it requires implementing
915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * that method as well as this one in the correct way.  Events will be
916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * received in the following order:
917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     *
918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * <ol>
919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * <li> You will receive the down event here.
920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * <li> The down event will be handled either by a child of this view
921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * group, or given to your own onTouchEvent() method to handle; this means
922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * you should implement onTouchEvent() to return true, so you will
923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * continue to see the rest of the gesture (instead of looking for
924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * a parent view to handle it).  Also, by returning true from
925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * onTouchEvent(), you will not receive any following
926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * events in onInterceptTouchEvent() and all touch processing must
927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * happen in onTouchEvent() like normal.
928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * <li> For as long as you return false from this function, each following
929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * event (up to and including the final up) will be delivered first here
930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * and then to the target's onTouchEvent().
931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * <li> If you return true from here, you will not receive any
932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * following events: the target view will receive the same event but
933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * with the action {@link MotionEvent#ACTION_CANCEL}, and all further
934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * events will be delivered to your onTouchEvent() method and no longer
935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * appear here.
936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * </ol>
937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     *
938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * @param ev The motion event being dispatched down the hierarchy.
939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * @return Return true to steal motion events from the children and have
940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * them dispatched to this ViewGroup through onTouchEvent().
941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * The current target will receive an ACTION_CANCEL event, and no further
942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * messages will be delivered here.
943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     */
944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    public boolean onInterceptTouchEvent(MotionEvent ev) {
945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        return false;
946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    /**
949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * {@inheritDoc}
950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     *
951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * Looks for a view to give focus to respecting the setting specified by
952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * {@link #getDescendantFocusability()}.
953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     *
954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * Uses {@link #onRequestFocusInDescendants(int, android.graphics.Rect)} to
955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * find focus within the children of this group when appropriate.
956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     *
957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * @see #FOCUS_BEFORE_DESCENDANTS
958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * @see #FOCUS_AFTER_DESCENDANTS
959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * @see #FOCUS_BLOCK_DESCENDANTS
960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * @see #onRequestFocusInDescendants
961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     */
962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    @Override
963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (DBG) {
9653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            System.out.println(this + " ViewGroup.requestFocus direction="
966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    + direction);
9676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        }
968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        int descendantFocusability = getDescendantFocusability();
969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        switch (descendantFocusability) {
971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case FOCUS_BLOCK_DESCENDANTS:
972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                return super.requestFocus(direction, previouslyFocusedRect);
973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case FOCUS_BEFORE_DESCENDANTS: {
974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                final boolean took = super.requestFocus(direction, previouslyFocusedRect);
975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                return took ? took : onRequestFocusInDescendants(direction, previouslyFocusedRect);
976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            }
977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            case FOCUS_AFTER_DESCENDANTS: {
978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                final boolean took = onRequestFocusInDescendants(direction, previouslyFocusedRect);
979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                return took ? took : super.requestFocus(direction, previouslyFocusedRect);
980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            }
981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            default:
982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                throw new IllegalStateException("descendant focusability must be "
983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        + "one of FOCUS_BEFORE_DESCENDANTS, FOCUS_AFTER_DESCENDANTS, FOCUS_BLOCK_DESCENDANTS "
984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        + "but is " + descendantFocusability);
985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
986a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    /**
989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * Look for a descendant to call {@link View#requestFocus} on.
990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * Called by {@link ViewGroup#requestFocus(int, android.graphics.Rect)}
991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * when it wants to request focus within its children.  Override this to
992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * customize how your {@link ViewGroup} requests focus within its children.
993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
994a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     *        to give a finer grained hint about where focus is coming from.  May be null
996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     *        if there is no hint.
997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * @return Whether focus was taken.
998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     */
999a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    @SuppressWarnings({"ConstantConditions"})
1000a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    protected boolean onRequestFocusInDescendants(int direction,
1001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            Rect previouslyFocusedRect) {
1002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        int index;
1003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        int increment;
1004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        int end;
1005a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        int count = mChildrenCount;
1006a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if ((direction & FOCUS_FORWARD) != 0) {
1007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            index = 0;
1008257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            increment = 1;
1009257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            end = count;
1010257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        } else {
1011257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            index = count - 1;
1012257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            increment = -1;
10133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            end = -1;
10143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
10153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        final View[] children = mChildren;
10163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        for (int i = index; i != end; i += increment) {
10173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            View child = children[i];
1018589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch            if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE) {
1019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                if (child.requestFocus(direction, previouslyFocusedRect)) {
1020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    return true;
102169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                }
102269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch            }
10233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
10243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        return false;
102569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    }
10263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    /**
10283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch     * {@inheritDoc}
10293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch     */
1030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    @Override
10313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    void dispatchAttachedToWindow(AttachInfo info, int visibility) {
10323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        super.dispatchAttachedToWindow(info, visibility);
10333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        visibility |= mViewFlags & VISIBILITY_MASK;
10343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        final int count = mChildrenCount;
1035e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        final View[] children = mChildren;
1036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        for (int i = 0; i < count; i++) {
1037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            children[i].dispatchAttachedToWindow(info, visibility);
10383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
1039a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    @Override
1042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
1043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        boolean populated = false;
1044257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        for (int i = 0, count = getChildCount(); i < count; i++) {
1045257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            populated |= getChildAt(i).dispatchPopulateAccessibilityEvent(event);
1046257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        }
1047257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        return populated;
1048257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
10493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    /**
10513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch     * {@inheritDoc}
10523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch     */
10533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    @Override
1054589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    void dispatchDetachedFromWindow() {
1055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // If we still have a motion target, we are still in the process of
1056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // dispatching motion events to a child; we need to get rid of that
105769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        // child to avoid dispatching events to it after the window is torn
105869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        // down. To make sure we keep the child in a consistent state, we
10593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // first send it an ACTION_CANCEL motion event.
10603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (mMotionTarget != null) {
106169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch            final long now = SystemClock.uptimeMillis();
10623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            final MotionEvent event = MotionEvent.obtain(now, now,
1063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    MotionEvent.ACTION_CANCEL, 0.0f, 0.0f, 0);
10643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            mMotionTarget.dispatchTouchEvent(event);
10653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            event.recycle();
10663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            mMotionTarget = null;
1067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
1068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        final int count = mChildrenCount;
1070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        final View[] children = mChildren;
1071a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        for (int i = 0; i < count; i++) {
1072a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            children[i].dispatchDetachedFromWindow();
1073a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
1074a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        super.dispatchDetachedFromWindow();
1075257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    }
1076257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1077257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    /**
1078257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch     * {@inheritDoc}
1079257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch     */
10803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    @Override
10813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    public void setPadding(int left, int top, int right, int bottom) {
10823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        super.setPadding(left, top, right, bottom);
10833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if ((mPaddingLeft | mPaddingTop | mPaddingRight | mPaddingRight) != 0) {
1085589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch            mGroupFlags |= FLAG_PADDING_NOT_NULL;
1086a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {
1087a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            mGroupFlags &= ~FLAG_PADDING_NOT_NULL;
108869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        }
108969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    }
10903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    /**
109269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch     * {@inheritDoc}
10933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch     */
1094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    @Override
10953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
10963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        super.dispatchSaveInstanceState(container);
10973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        final int count = mChildrenCount;
1098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        final View[] children = mChildren;
1099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        for (int i = 0; i < count; i++) {
1100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            children[i].dispatchSaveInstanceState(container);
1101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
1102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    /**
1105257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch     * Perform dispatching of a {@link #saveHierarchyState freeze()} to only this view,
1106257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch     * not to its children.  For use when overriding
1107257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch     * {@link #dispatchSaveInstanceState dispatchFreeze()} to allow subclasses to freeze
1108257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch     * their own state but not the state of their children.
1109257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch     *
11103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch     * @param container the container
11113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch     */
11123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    protected void dispatchFreezeSelfOnly(SparseArray<Parcelable> container) {
11133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        super.dispatchSaveInstanceState(container);
11143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
1115589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
1116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    /**
1117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * {@inheritDoc}
111869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch     */
111969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    @Override
11203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
11213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        super.dispatchRestoreInstanceState(container);
112269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        final int count = mChildrenCount;
11233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        final View[] children = mChildren;
1124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        for (int i = 0; i < count; i++) {
11253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            children[i].dispatchRestoreInstanceState(container);
11263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
11273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
1128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    /**
1130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * Perform dispatching of a {@link #restoreHierarchyState thaw()} to only this view,
1131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * not to its children.  For use when overriding
1132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * {@link #dispatchRestoreInstanceState dispatchThaw()} to allow subclasses to thaw
1133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * their own state but not the state of their children.
1134257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch     *
1135257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch     * @param container the container
1136257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch     */
1137257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    protected void dispatchThawSelfOnly(SparseArray<Parcelable> container) {
1138257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        super.dispatchRestoreInstanceState(container);
11393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
11403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
11413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    /**
11423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch     * Enables or disables the drawing cache for each child of this view group.
11433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch     *
1144589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch     * @param enabled true to enable the cache, false to dispose of it
1145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     */
1146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    protected void setChildrenDrawingCacheEnabled(boolean enabled) {
114769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        if (enabled || (mPersistentDrawingCache & PERSISTENT_ALL_CACHES) != PERSISTENT_ALL_CACHES) {
114869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch            final View[] children = mChildren;
11493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            final int count = mChildrenCount;
11503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            for (int i = 0; i < count; i++) {
115169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                children[i].setDrawingCacheEnabled(enabled);
11523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            }
1153e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        }
1154e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
1155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    @Override
11573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    protected void onAnimationStart() {
11583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        super.onAnimationStart();
1159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // When this ViewGroup's animation starts, build the cache for the children
1161e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        if ((mGroupFlags & FLAG_ANIMATION_CACHE) == FLAG_ANIMATION_CACHE) {
1162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            final int count = mChildrenCount;
1163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            final View[] children = mChildren;
1164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            for (int i = 0; i < count; i++) {
1166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                final View child = children[i];
1167257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE) {
1168257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                    child.setDrawingCacheEnabled(true);
1169257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                    child.buildDrawingCache();
1170257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                }
1171257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            }
117280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
117380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen            mGroupFlags |= FLAG_CHILDREN_DRAWN_WITH_CACHE;
11748defd9ff6930b4e24729971a61cf7469daf119beSteve Block        }
1175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    @Override
1178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    protected void onAnimationEnd() {
11791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        super.onAnimationEnd();
11801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
11811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        // When this ViewGroup's animation ends, destroy the cache of the children
11821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        if ((mGroupFlags & FLAG_ANIMATION_CACHE) == FLAG_ANIMATION_CACHE) {
11831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block            mGroupFlags &= ~FLAG_CHILDREN_DRAWN_WITH_CACHE;
1184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
118559151504615d929945dc59db37bf1166937748c6Steve Block            if ((mPersistentDrawingCache & PERSISTENT_ANIMATION_CACHE) == 0) {
118659151504615d929945dc59db37bf1166937748c6Steve Block                setChildrenDrawingCacheEnabled(false);
1187e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch            }
118859151504615d929945dc59db37bf1166937748c6Steve Block        }
118959151504615d929945dc59db37bf1166937748c6Steve Block    }
119059151504615d929945dc59db37bf1166937748c6Steve Block
119159151504615d929945dc59db37bf1166937748c6Steve Block    /**
119259151504615d929945dc59db37bf1166937748c6Steve Block     * {@inheritDoc}
1193e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch     */
119459151504615d929945dc59db37bf1166937748c6Steve Block    @Override
119559151504615d929945dc59db37bf1166937748c6Steve Block    protected void dispatchDraw(Canvas canvas) {
119659151504615d929945dc59db37bf1166937748c6Steve Block        final int count = mChildrenCount;
119759151504615d929945dc59db37bf1166937748c6Steve Block        final View[] children = mChildren;
119859151504615d929945dc59db37bf1166937748c6Steve Block        int flags = mGroupFlags;
119959151504615d929945dc59db37bf1166937748c6Steve Block
120059151504615d929945dc59db37bf1166937748c6Steve Block        if ((flags & FLAG_RUN_ANIMATION) != 0 && canAnimate()) {
120159151504615d929945dc59db37bf1166937748c6Steve Block            final boolean cache = (mGroupFlags & FLAG_ANIMATION_CACHE) == FLAG_ANIMATION_CACHE;
120259151504615d929945dc59db37bf1166937748c6Steve Block
120359151504615d929945dc59db37bf1166937748c6Steve Block            for (int i = 0; i < count; i++) {
120459151504615d929945dc59db37bf1166937748c6Steve Block                final View child = children[i];
120559151504615d929945dc59db37bf1166937748c6Steve Block                if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE) {
120659151504615d929945dc59db37bf1166937748c6Steve Block                    final LayoutParams params = child.getLayoutParams();
120759151504615d929945dc59db37bf1166937748c6Steve Block                    attachLayoutAnimationParameters(child, params, i, count);
120859151504615d929945dc59db37bf1166937748c6Steve Block                    bindLayoutAnimation(child);
120959151504615d929945dc59db37bf1166937748c6Steve Block                    if (cache) {
121059151504615d929945dc59db37bf1166937748c6Steve Block                        child.setDrawingCacheEnabled(true);
121180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                        child.buildDrawingCache();
12126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                    }
121359151504615d929945dc59db37bf1166937748c6Steve Block                }
12146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            }
12156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            final LayoutAnimationController controller = mLayoutAnimationController;
12176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            if (controller.willOverlap()) {
121859151504615d929945dc59db37bf1166937748c6Steve Block                mGroupFlags |= FLAG_OPTIMIZE_INVALIDATE;
121959151504615d929945dc59db37bf1166937748c6Steve Block            }
12206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            controller.start();
1222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            mGroupFlags &= ~FLAG_RUN_ANIMATION;
1224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            mGroupFlags &= ~FLAG_ANIMATION_DONE;
1225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            if (cache) {
1227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                mGroupFlags |= FLAG_CHILDREN_DRAWN_WITH_CACHE;
1228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            }
1229257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1230257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            if (mAnimationListener != null) {
1231257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                mAnimationListener.onAnimationStart(controller.getAnimation());
1232257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            }
1233257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        }
123480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
123580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        int saveCount = 0;
12368defd9ff6930b4e24729971a61cf7469daf119beSteve Block        final boolean clipToPadding = (flags & CLIP_TO_PADDING_MASK) == CLIP_TO_PADDING_MASK;
1237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (clipToPadding) {
1238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            saveCount = canvas.save();
1239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            canvas.clipRect(mScrollX + mPaddingLeft, mScrollY + mPaddingTop,
1240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    mScrollX + mRight - mLeft - mPaddingRight,
124159151504615d929945dc59db37bf1166937748c6Steve Block                    mScrollY + mBottom - mTop - mPaddingBottom);
1242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
124359151504615d929945dc59db37bf1166937748c6Steve Block        }
1244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // We will draw our child's animation, let's reset the flag
124659151504615d929945dc59db37bf1166937748c6Steve Block        mPrivateFlags &= ~DRAW_ANIMATION;
124759151504615d929945dc59db37bf1166937748c6Steve Block        mGroupFlags &= ~FLAG_INVALIDATE_REQUIRED;
1248e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
124959151504615d929945dc59db37bf1166937748c6Steve Block        boolean more = false;
125059151504615d929945dc59db37bf1166937748c6Steve Block        final long drawingTime = getDrawingTime();
125159151504615d929945dc59db37bf1166937748c6Steve Block
125259151504615d929945dc59db37bf1166937748c6Steve Block        if ((flags & FLAG_USE_CHILD_DRAWING_ORDER) == 0) {
125359151504615d929945dc59db37bf1166937748c6Steve Block            for (int i = 0; i < count; i++) {
1254e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                final View child = children[i];
125559151504615d929945dc59db37bf1166937748c6Steve Block                if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE || child.getAnimation() != null) {
125659151504615d929945dc59db37bf1166937748c6Steve Block                    more |= drawChild(canvas, child, drawingTime);
125759151504615d929945dc59db37bf1166937748c6Steve Block                }
125859151504615d929945dc59db37bf1166937748c6Steve Block            }
125959151504615d929945dc59db37bf1166937748c6Steve Block        } else {
126059151504615d929945dc59db37bf1166937748c6Steve Block            for (int i = 0; i < count; i++) {
126159151504615d929945dc59db37bf1166937748c6Steve Block                final View child = children[getChildDrawingOrder(count, i)];
126259151504615d929945dc59db37bf1166937748c6Steve Block                if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE || child.getAnimation() != null) {
126359151504615d929945dc59db37bf1166937748c6Steve Block                    more |= drawChild(canvas, child, drawingTime);
126459151504615d929945dc59db37bf1166937748c6Steve Block                }
126559151504615d929945dc59db37bf1166937748c6Steve Block            }
126659151504615d929945dc59db37bf1166937748c6Steve Block        }
126759151504615d929945dc59db37bf1166937748c6Steve Block
126859151504615d929945dc59db37bf1166937748c6Steve Block        // Draw any disappearing views that have animations
126959151504615d929945dc59db37bf1166937748c6Steve Block        if (mDisappearingChildren != null) {
1270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            final ArrayList<View> disappearingChildren = mDisappearingChildren;
12716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            final int disappearingCount = disappearingChildren.size() - 1;
127259151504615d929945dc59db37bf1166937748c6Steve Block            // Go backwards -- we may delete as animations finish
12736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            for (int i = disappearingCount; i >= 0; i--) {
12746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                final View child = disappearingChildren.get(i);
12756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                more |= drawChild(canvas, child, drawingTime);
12766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            }
127759151504615d929945dc59db37bf1166937748c6Steve Block        }
12786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        if (clipToPadding) {
1280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            canvas.restoreToCount(saveCount);
1281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
1282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // mGroupFlags might have been updated by drawChild()
1284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        flags = mGroupFlags;
1285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if ((flags & FLAG_INVALIDATE_REQUIRED) == FLAG_INVALIDATE_REQUIRED) {
1287257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            invalidate();
1288257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        }
1289257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
1290257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        if ((flags & FLAG_ANIMATION_DONE) == 0 && (flags & FLAG_NOTIFY_ANIMATION_LISTENER) == 0 &&
1291257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                mLayoutAnimationController.isDone() && !more) {
12923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            // We want to erase the drawing cache and notify the listener after the
12933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            // next frame is drawn because one extra invalidate() is caused by
12943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            // drawChild() after the animation is over
12953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            mGroupFlags |= FLAG_NOTIFY_ANIMATION_LISTENER;
12963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            final Runnable end = new Runnable() {
1297589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch               public void run() {
1298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                   notifyAnimationListener();
1299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block               }
130069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch            };
1301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            post(end);
1302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
1303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
13043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    /**
1306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * Returns the index of the child to draw for this iteration. Override this
1307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * if you want to change the drawing order of children. By default, it
1308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * returns i.
1309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * <p>
1310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * NOTE: In order for this method to be called, the
1311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * {@link #FLAG_USE_CHILD_DRAWING_ORDER} must be set.
1312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     *
131369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch     * @param i The current iteration.
1314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * @return The index of the child to draw this iteration.
13153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch     */
13163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    protected int getChildDrawingOrder(int childCount, int i) {
13173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        return i;
1318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    private void notifyAnimationListener() {
1321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        mGroupFlags &= ~FLAG_NOTIFY_ANIMATION_LISTENER;
1322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        mGroupFlags |= FLAG_ANIMATION_DONE;
1323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1324257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        if (mAnimationListener != null) {
1325257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch           final Runnable end = new Runnable() {
1326257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch               public void run() {
1327257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                   mAnimationListener.onAnimationEnd(mLayoutAnimationController.getAnimation());
1328257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch               }
13293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           };
13303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           post(end);
13313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
13323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if ((mGroupFlags & FLAG_ANIMATION_CACHE) == FLAG_ANIMATION_CACHE) {
1334589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch            mGroupFlags &= ~FLAG_CHILDREN_DRAWN_WITH_CACHE;
1335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            if ((mPersistentDrawingCache & PERSISTENT_ANIMATION_CACHE) == 0) {
1336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                setChildrenDrawingCacheEnabled(false);
1337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            }
13383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
1339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        invalidate();
13413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
13423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    /**
1344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * Draw one child of this View Group. This method is responsible for getting
1345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * the canvas in the right state. This includes clipping, translating so
1346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * that the child's scrolled origin is at 0, 0, and applying any animation
1347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * transformations.
1348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     *
1349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * @param canvas The canvas on which to draw the child
135069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch     * @param child Who to draw
1351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     * @param drawingTime The time at which draw is occuring
13523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch     * @return True if an invalidate() was issued
13533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch     */
13543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
1355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        boolean more = false;
1356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        final int cl = child.mLeft;
1358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        final int ct = child.mTop;
1359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        final int cr = child.mRight;
13603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block        final int cb = child.mBottom;
13613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
13623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block        final int flags = mGroupFlags;
13633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if ((flags & FLAG_CLEAR_TRANSFORMATION) == FLAG_CLEAR_TRANSFORMATION) {
1365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            if (mChildTransformation != null) {
1366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                mChildTransformation.clear();
1367589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch            }
1368589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch            mGroupFlags &= ~FLAG_CLEAR_TRANSFORMATION;
1369589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        }
1370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Transformation transformToApply = null;
1372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        final Animation a = child.getAnimation();
1373589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        boolean concatMatrix = false;
13743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
13753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block        if (a != null) {
13763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block            if (mInvalidateRegion == null) {
13773ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                mInvalidateRegion = new RectF();
13786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            }
13796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            final RectF region = mInvalidateRegion;
13803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            final boolean initialized = a.isInitialized();
13826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            if (!initialized) {
13836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                a.initialize(cr - cl, cb - ct, getWidth(), getHeight());
13846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                a.initializeInvalidateRegion(0, 0, cr - cl, cb - ct);
13856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                child.onAnimationStart();
13866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            }
13876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            if (mChildTransformation == null) {
13893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                mChildTransformation = new Transformation();
13906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            }
1391589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch            more = a.getTransformation(drawingTime, mChildTransformation);
1392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            transformToApply = mChildTransformation;
1393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            concatMatrix = a.willChangeTransformationMatrix();
13953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            if (more) {
13976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                if (!a.willChangeBounds()) {
13986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                    if ((flags & (FLAG_OPTIMIZE_INVALIDATE | FLAG_ANIMATION_DONE)) ==
13996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                            FLAG_OPTIMIZE_INVALIDATE) {
14006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                        mGroupFlags |= FLAG_INVALIDATE_REQUIRED;
14016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                    } else if ((flags & FLAG_INVALIDATE_REQUIRED) == 0) {
14026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                        // The child need to draw an animation, potentially offscreen, so
14036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                        // make sure we do not cancel invalidate requests
14046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                        mPrivateFlags |= DRAW_ANIMATION;
14056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                        invalidate(cl, ct, cr, cb);
14066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                    }
14076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                } else {
14086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                    a.getInvalidateRegion(0, 0, cr - cl, cb - ct, region, transformToApply);
14096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                    // The child need to draw an animation, potentially offscreen, so
14116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                    // make sure we do not cancel invalidate requests
14126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                    mPrivateFlags |= DRAW_ANIMATION;
14136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                    final int left = cl + (int) region.left;
14156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                    final int top = ct + (int) region.top;
14166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                    invalidate(left, top, left + (int) region.width(), top + (int) region.height());
14176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                }
14186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            }
14196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        } else if ((flags & FLAG_SUPPORT_STATIC_TRANSFORMATIONS) ==
1420e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                FLAG_SUPPORT_STATIC_TRANSFORMATIONS) {
1421e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch            if (mChildTransformation == null) {
1422589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                mChildTransformation = new Transformation();
1423589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch            }
1424589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch            final boolean hasTransform = getChildStaticTransformation(child, mChildTransformation);
1425589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch            if (hasTransform) {
1426589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                final int transformType = mChildTransformation.getTransformationType();
1427589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                transformToApply = transformType != Transformation.TYPE_IDENTITY ?
1428589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                        mChildTransformation : null;
1429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
1430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            }
1431589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        }
1432
1433        // Sets the flag as early as possible to allow draw() implementations
1434        // to call invalidate() successfully when doing animations
1435        child.mPrivateFlags |= DRAWN;
1436
1437        if (!concatMatrix && canvas.quickReject(cl, ct, cr, cb, Canvas.EdgeType.BW) &&
1438                (child.mPrivateFlags & DRAW_ANIMATION) == 0) {
1439            return more;
1440        }
1441
1442        child.computeScroll();
1443
1444        final int sx = child.mScrollX;
1445        final int sy = child.mScrollY;
1446
1447        Bitmap cache = null;
1448        if ((flags & FLAG_CHILDREN_DRAWN_WITH_CACHE) == FLAG_CHILDREN_DRAWN_WITH_CACHE ||
1449                (flags & FLAG_ALWAYS_DRAWN_WITH_CACHE) == FLAG_ALWAYS_DRAWN_WITH_CACHE) {
1450            cache = child.getDrawingCache();
1451        }
1452
1453        final boolean hasNoCache = cache == null;
1454
1455        final int restoreTo = canvas.save();
1456        if (hasNoCache) {
1457            canvas.translate(cl - sx, ct - sy);
1458        } else {
1459            canvas.translate(cl, ct);
1460        }
1461
1462        float alpha = 1.0f;
1463
1464        if (transformToApply != null) {
1465            if (concatMatrix) {
1466                int transX = 0;
1467                int transY = 0;
1468                if (hasNoCache) {
1469                    transX = -sx;
1470                    transY = -sy;
1471                }
1472                // Undo the scroll translation, apply the transformation matrix,
1473                // then redo the scroll translate to get the correct result.
1474                canvas.translate(-transX, -transY);
1475                canvas.concat(transformToApply.getMatrix());
1476                canvas.translate(transX, transY);
1477                mGroupFlags |= FLAG_CLEAR_TRANSFORMATION;
1478            }
1479
1480            alpha = transformToApply.getAlpha();
1481            if (alpha < 1.0f) {
1482                mGroupFlags |= FLAG_CLEAR_TRANSFORMATION;
1483            }
1484
1485            if (alpha < 1.0f && hasNoCache) {
1486                final int multipliedAlpha = (int) (255 * alpha);
1487                if (!child.onSetAlpha(multipliedAlpha)) {
1488                    canvas.saveLayerAlpha(sx, sy, sx + cr - cl, sy + cb - ct, multipliedAlpha,
1489                            Canvas.HAS_ALPHA_LAYER_SAVE_FLAG | Canvas.CLIP_TO_LAYER_SAVE_FLAG);
1490                } else {
1491                    child.mPrivateFlags |= ALPHA_SET;
1492                }
1493            }
1494        } else if ((child.mPrivateFlags & ALPHA_SET) == ALPHA_SET) {
1495            child.onSetAlpha(255);
1496        }
1497
1498        if ((flags & FLAG_CLIP_CHILDREN) == FLAG_CLIP_CHILDREN) {
1499            if (hasNoCache) {
1500                canvas.clipRect(sx, sy, sx + (cr - cl), sy + (cb - ct));
1501            } else {
1502                canvas.clipRect(0, 0, cr - cl, cb - ct);
1503            }
1504        }
1505
1506        if (hasNoCache) {
1507            // Fast path for layouts with no backgrounds
1508            if ((child.mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
1509                if (ViewDebug.TRACE_HIERARCHY) {
1510                    ViewDebug.trace(this, ViewDebug.HierarchyTraceType.DRAW);
1511                }
1512                child.mPrivateFlags &= ~DIRTY_MASK;
1513                child.dispatchDraw(canvas);
1514            } else {
1515                child.draw(canvas);
1516            }
1517        } else {
1518            final Paint cachePaint = mCachePaint;
1519            if (alpha < 1.0f) {
1520                cachePaint.setAlpha((int) (alpha * 255));
1521                mGroupFlags |= FLAG_ALPHA_LOWER_THAN_ONE;
1522            } else if  ((flags & FLAG_ALPHA_LOWER_THAN_ONE) == FLAG_ALPHA_LOWER_THAN_ONE) {
1523                cachePaint.setAlpha(255);
1524                mGroupFlags &= ~FLAG_ALPHA_LOWER_THAN_ONE;
1525            }
1526            if (Config.DEBUG && ViewDebug.profileDrawing) {
1527                EventLog.writeEvent(60003, hashCode());
1528            }
1529            canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
1530        }
1531
1532        canvas.restoreToCount(restoreTo);
1533
1534        if (a != null && !more) {
1535            child.onSetAlpha(255);
1536            finishAnimatingView(child, a);
1537        }
1538
1539        return more;
1540    }
1541
1542    /**
1543     * By default, children are clipped to their bounds before drawing. This
1544     * allows view groups to override this behavior for animations, etc.
1545     *
1546     * @param clipChildren true to clip children to their bounds,
1547     *        false otherwise
1548     * @attr ref android.R.styleable#ViewGroup_clipChildren
1549     */
1550    public void setClipChildren(boolean clipChildren) {
1551        setBooleanFlag(FLAG_CLIP_CHILDREN, clipChildren);
1552    }
1553
1554    /**
1555     * By default, children are clipped to the padding of the ViewGroup. This
1556     * allows view groups to override this behavior
1557     *
1558     * @param clipToPadding true to clip children to the padding of the
1559     *        group, false otherwise
1560     * @attr ref android.R.styleable#ViewGroup_clipToPadding
1561     */
1562    public void setClipToPadding(boolean clipToPadding) {
1563        setBooleanFlag(FLAG_CLIP_TO_PADDING, clipToPadding);
1564    }
1565
1566    /**
1567     * {@inheritDoc}
1568     */
1569    @Override
1570    public void dispatchSetSelected(boolean selected) {
1571        final View[] children = mChildren;
1572        final int count = mChildrenCount;
1573        for (int i = 0; i < count; i++) {
1574            children[i].setSelected(selected);
1575        }
1576    }
1577
1578    @Override
1579    protected void dispatchSetPressed(boolean pressed) {
1580        final View[] children = mChildren;
1581        final int count = mChildrenCount;
1582        for (int i = 0; i < count; i++) {
1583            children[i].setPressed(pressed);
1584        }
1585    }
1586
1587    /**
1588     * When this property is set to true, this ViewGroup supports static transformations on
1589     * children; this causes
1590     * {@link #getChildStaticTransformation(View, android.view.animation.Transformation)} to be
1591     * invoked when a child is drawn.
1592     *
1593     * Any subclass overriding
1594     * {@link #getChildStaticTransformation(View, android.view.animation.Transformation)} should
1595     * set this property to true.
1596     *
1597     * @param enabled True to enable static transformations on children, false otherwise.
1598     *
1599     * @see #FLAG_SUPPORT_STATIC_TRANSFORMATIONS
1600     */
1601    protected void setStaticTransformationsEnabled(boolean enabled) {
1602        setBooleanFlag(FLAG_SUPPORT_STATIC_TRANSFORMATIONS, enabled);
1603    }
1604
1605    /**
1606     * {@inheritDoc}
1607     *
1608     * @see #setStaticTransformationsEnabled(boolean)
1609     */
1610    protected boolean getChildStaticTransformation(View child, Transformation t) {
1611        return false;
1612    }
1613
1614    /**
1615     * {@hide}
1616     */
1617    @Override
1618    protected View findViewTraversal(int id) {
1619        if (id == mID) {
1620            return this;
1621        }
1622
1623        final View[] where = mChildren;
1624        final int len = mChildrenCount;
1625
1626        for (int i = 0; i < len; i++) {
1627            View v = where[i];
1628
1629            if ((v.mPrivateFlags & IS_ROOT_NAMESPACE) == 0) {
1630                v = v.findViewById(id);
1631
1632                if (v != null) {
1633                    return v;
1634                }
1635            }
1636        }
1637
1638        return null;
1639    }
1640
1641    /**
1642     * {@hide}
1643     */
1644    @Override
1645    protected View findViewWithTagTraversal(Object tag) {
1646        if (tag != null && tag.equals(mTag)) {
1647            return this;
1648        }
1649
1650        final View[] where = mChildren;
1651        final int len = mChildrenCount;
1652
1653        for (int i = 0; i < len; i++) {
1654            View v = where[i];
1655
1656            if ((v.mPrivateFlags & IS_ROOT_NAMESPACE) == 0) {
1657                v = v.findViewWithTag(tag);
1658
1659                if (v != null) {
1660                    return v;
1661                }
1662            }
1663        }
1664
1665        return null;
1666    }
1667
1668    /**
1669     * Adds a child view. If no layout parameters are already set on the child, the
1670     * default parameters for this ViewGroup are set on the child.
1671     *
1672     * @param child the child view to add
1673     *
1674     * @see #generateDefaultLayoutParams()
1675     */
1676    public void addView(View child) {
1677        addView(child, -1);
1678    }
1679
1680    /**
1681     * Adds a child view. If no layout parameters are already set on the child, the
1682     * default parameters for this ViewGroup are set on the child.
1683     *
1684     * @param child the child view to add
1685     * @param index the position at which to add the child
1686     *
1687     * @see #generateDefaultLayoutParams()
1688     */
1689    public void addView(View child, int index) {
1690        LayoutParams params = child.getLayoutParams();
1691        if (params == null) {
1692            params = generateDefaultLayoutParams();
1693            if (params == null) {
1694                throw new IllegalArgumentException("generateDefaultLayoutParams() cannot return null");
1695            }
1696        }
1697        addView(child, index, params);
1698    }
1699
1700    /**
1701     * Adds a child view with this ViewGroup's default layout parameters and the
1702     * specified width and height.
1703     *
1704     * @param child the child view to add
1705     */
1706    public void addView(View child, int width, int height) {
1707        final LayoutParams params = generateDefaultLayoutParams();
1708        params.width = width;
1709        params.height = height;
1710        addView(child, -1, params);
1711    }
1712
1713    /**
1714     * Adds a child view with the specified layout parameters.
1715     *
1716     * @param child the child view to add
1717     * @param params the layout parameters to set on the child
1718     */
1719    public void addView(View child, LayoutParams params) {
1720        addView(child, -1, params);
1721    }
1722
1723    /**
1724     * Adds a child view with the specified layout parameters.
1725     *
1726     * @param child the child view to add
1727     * @param index the position at which to add the child
1728     * @param params the layout parameters to set on the child
1729     */
1730    public void addView(View child, int index, LayoutParams params) {
1731        if (DBG) {
1732            System.out.println(this + " addView");
1733        }
1734
1735        // addViewInner() will call child.requestLayout() when setting the new LayoutParams
1736        // therefore, we call requestLayout() on ourselves before, so that the child's request
1737        // will be blocked at our level
1738        requestLayout();
1739        invalidate();
1740        addViewInner(child, index, params, false);
1741    }
1742
1743    /**
1744     * {@inheritDoc}
1745     */
1746    public void updateViewLayout(View view, ViewGroup.LayoutParams params) {
1747        if (!checkLayoutParams(params)) {
1748            throw new IllegalArgumentException("Invalid LayoutParams supplied to " + this);
1749        }
1750        if (view.mParent != this) {
1751            throw new IllegalArgumentException("Given view not a child of " + this);
1752        }
1753        view.setLayoutParams(params);
1754    }
1755
1756    /**
1757     * {@inheritDoc}
1758     */
1759    protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
1760        return  p != null;
1761    }
1762
1763    /**
1764     * Interface definition for a callback to be invoked when the hierarchy
1765     * within this view changed. The hierarchy changes whenever a child is added
1766     * to or removed from this view.
1767     */
1768    public interface OnHierarchyChangeListener {
1769        /**
1770         * Called when a new child is added to a parent view.
1771         *
1772         * @param parent the view in which a child was added
1773         * @param child the new child view added in the hierarchy
1774         */
1775        void onChildViewAdded(View parent, View child);
1776
1777        /**
1778         * Called when a child is removed from a parent view.
1779         *
1780         * @param parent the view from which the child was removed
1781         * @param child the child removed from the hierarchy
1782         */
1783        void onChildViewRemoved(View parent, View child);
1784    }
1785
1786    /**
1787     * Register a callback to be invoked when a child is added to or removed
1788     * from this view.
1789     *
1790     * @param listener the callback to invoke on hierarchy change
1791     */
1792    public void setOnHierarchyChangeListener(OnHierarchyChangeListener listener) {
1793        mOnHierarchyChangeListener = listener;
1794    }
1795
1796    /**
1797     * Adds a view during layout. This is useful if in your onLayout() method,
1798     * you need to add more views (as does the list view for example).
1799     *
1800     * If index is negative, it means put it at the end of the list.
1801     *
1802     * @param child the view to add to the group
1803     * @param index the index at which the child must be added
1804     * @param params the layout parameters to associate with the child
1805     * @return true if the child was added, false otherwise
1806     */
1807    protected boolean addViewInLayout(View child, int index, LayoutParams params) {
1808        return addViewInLayout(child, index, params, false);
1809    }
1810
1811    /**
1812     * Adds a view during layout. This is useful if in your onLayout() method,
1813     * you need to add more views (as does the list view for example).
1814     *
1815     * If index is negative, it means put it at the end of the list.
1816     *
1817     * @param child the view to add to the group
1818     * @param index the index at which the child must be added
1819     * @param params the layout parameters to associate with the child
1820     * @param preventRequestLayout if true, calling this method will not trigger a
1821     *        layout request on child
1822     * @return true if the child was added, false otherwise
1823     */
1824    protected boolean addViewInLayout(View child, int index, LayoutParams params,
1825            boolean preventRequestLayout) {
1826        child.mParent = null;
1827        addViewInner(child, index, params, preventRequestLayout);
1828        child.mPrivateFlags = (child.mPrivateFlags & ~DIRTY_MASK) | DRAWN;
1829        return true;
1830    }
1831
1832    /**
1833     * Prevents the specified child to be laid out during the next layout pass.
1834     *
1835     * @param child the child on which to perform the cleanup
1836     */
1837    protected void cleanupLayoutState(View child) {
1838        child.mPrivateFlags &= ~View.FORCE_LAYOUT;
1839    }
1840
1841    private void addViewInner(View child, int index, LayoutParams params,
1842            boolean preventRequestLayout) {
1843
1844        if (child.getParent() != null) {
1845            throw new IllegalStateException("The specified child already has a parent. " +
1846                    "You must call removeView() on the child's parent first.");
1847        }
1848
1849        if (!checkLayoutParams(params)) {
1850            params = generateLayoutParams(params);
1851        }
1852
1853        if (preventRequestLayout) {
1854            child.mLayoutParams = params;
1855        } else {
1856            child.setLayoutParams(params);
1857        }
1858
1859        if (index < 0) {
1860            index = mChildrenCount;
1861        }
1862
1863        addInArray(child, index);
1864
1865        // tell our children
1866        if (preventRequestLayout) {
1867            child.assignParent(this);
1868        } else {
1869            child.mParent = this;
1870        }
1871
1872        if (child.hasFocus()) {
1873            requestChildFocus(child, child.findFocus());
1874        }
1875
1876        AttachInfo ai = mAttachInfo;
1877        if (ai != null) {
1878            boolean lastKeepOn = ai.mKeepScreenOn;
1879            ai.mKeepScreenOn = false;
1880            child.dispatchAttachedToWindow(mAttachInfo, (mViewFlags&VISIBILITY_MASK));
1881            if (ai.mKeepScreenOn) {
1882                needGlobalAttributesUpdate(true);
1883            }
1884            ai.mKeepScreenOn = lastKeepOn;
1885        }
1886
1887        if (mOnHierarchyChangeListener != null) {
1888            mOnHierarchyChangeListener.onChildViewAdded(this, child);
1889        }
1890
1891        if ((child.mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE) {
1892            mGroupFlags |= FLAG_NOTIFY_CHILDREN_ON_DRAWABLE_STATE_CHANGE;
1893        }
1894    }
1895
1896    private void addInArray(View child, int index) {
1897        View[] children = mChildren;
1898        final int count = mChildrenCount;
1899        final int size = children.length;
1900        if (index == count) {
1901            if (size == count) {
1902                mChildren = new View[size + ARRAY_CAPACITY_INCREMENT];
1903                System.arraycopy(children, 0, mChildren, 0, size);
1904                children = mChildren;
1905            }
1906            children[mChildrenCount++] = child;
1907        } else if (index < count) {
1908            if (size == count) {
1909                mChildren = new View[size + ARRAY_CAPACITY_INCREMENT];
1910                System.arraycopy(children, 0, mChildren, 0, index);
1911                System.arraycopy(children, index, mChildren, index + 1, count - index);
1912                children = mChildren;
1913            } else {
1914                System.arraycopy(children, index, children, index + 1, count - index);
1915            }
1916            children[index] = child;
1917            mChildrenCount++;
1918        } else {
1919            throw new IndexOutOfBoundsException("index=" + index + " count=" + count);
1920        }
1921    }
1922
1923    // This method also sets the child's mParent to null
1924    private void removeFromArray(int index) {
1925        final View[] children = mChildren;
1926        children[index].mParent = null;
1927        final int count = mChildrenCount;
1928        if (index == count - 1) {
1929            children[--mChildrenCount] = null;
1930        } else if (index >= 0 && index < count) {
1931            System.arraycopy(children, index + 1, children, index, count - index - 1);
1932            children[--mChildrenCount] = null;
1933        } else {
1934            throw new IndexOutOfBoundsException();
1935        }
1936    }
1937
1938    // This method also sets the children's mParent to null
1939    private void removeFromArray(int start, int count) {
1940        final View[] children = mChildren;
1941        final int childrenCount = mChildrenCount;
1942
1943        start = Math.max(0, start);
1944        final int end = Math.min(childrenCount, start + count);
1945
1946        if (start == end) {
1947            return;
1948        }
1949
1950        if (end == childrenCount) {
1951            for (int i = start; i < end; i++) {
1952                children[i].mParent = null;
1953                children[i] = null;
1954            }
1955        } else {
1956            for (int i = start; i < end; i++) {
1957                children[i].mParent = null;
1958            }
1959
1960            // Since we're looping above, we might as well do the copy, but is arraycopy()
1961            // faster than the extra 2 bounds checks we would do in the loop?
1962            System.arraycopy(children, end, children, start, childrenCount - end);
1963
1964            for (int i = childrenCount - (end - start); i < childrenCount; i++) {
1965                children[i] = null;
1966            }
1967        }
1968
1969        mChildrenCount -= (end - start);
1970    }
1971
1972    private void bindLayoutAnimation(View child) {
1973        Animation a = mLayoutAnimationController.getAnimationForView(child);
1974        child.setAnimation(a);
1975    }
1976
1977    /**
1978     * Subclasses should override this method to set layout animation
1979     * parameters on the supplied child.
1980     *
1981     * @param child the child to associate with animation parameters
1982     * @param params the child's layout parameters which hold the animation
1983     *        parameters
1984     * @param index the index of the child in the view group
1985     * @param count the number of children in the view group
1986     */
1987    protected void attachLayoutAnimationParameters(View child,
1988            LayoutParams params, int index, int count) {
1989        LayoutAnimationController.AnimationParameters animationParams =
1990                    params.layoutAnimationParameters;
1991        if (animationParams == null) {
1992            animationParams = new LayoutAnimationController.AnimationParameters();
1993            params.layoutAnimationParameters = animationParams;
1994        }
1995
1996        animationParams.count = count;
1997        animationParams.index = index;
1998    }
1999
2000    /**
2001     * {@inheritDoc}
2002     */
2003    public void removeView(View view) {
2004        removeViewInternal(view);
2005        requestLayout();
2006        invalidate();
2007    }
2008
2009    /**
2010     * Removes a view during layout. This is useful if in your onLayout() method,
2011     * you need to remove more views.
2012     *
2013     * @param view the view to remove from the group
2014     */
2015    public void removeViewInLayout(View view) {
2016        removeViewInternal(view);
2017    }
2018
2019    /**
2020     * Removes a range of views during layout. This is useful if in your onLayout() method,
2021     * you need to remove more views.
2022     *
2023     * @param start the index of the first view to remove from the group
2024     * @param count the number of views to remove from the group
2025     */
2026    public void removeViewsInLayout(int start, int count) {
2027        removeViewsInternal(start, count);
2028    }
2029
2030    /**
2031     * Removes the view at the specified position in the group.
2032     *
2033     * @param index the position in the group of the view to remove
2034     */
2035    public void removeViewAt(int index) {
2036        removeViewInternal(index, getChildAt(index));
2037        requestLayout();
2038        invalidate();
2039    }
2040
2041    /**
2042     * Removes the specified range of views from the group.
2043     *
2044     * @param start the first position in the group of the range of views to remove
2045     * @param count the number of views to remove
2046     */
2047    public void removeViews(int start, int count) {
2048        removeViewsInternal(start, count);
2049        requestLayout();
2050        invalidate();
2051    }
2052
2053    private void removeViewInternal(View view) {
2054        final int index = indexOfChild(view);
2055        if (index >= 0) {
2056            removeViewInternal(index, view);
2057        }
2058    }
2059
2060    private void removeViewInternal(int index, View view) {
2061        boolean clearChildFocus = false;
2062        if (view == mFocused) {
2063            view.clearFocusForRemoval();
2064            clearChildFocus = true;
2065        }
2066
2067        if (view.getAnimation() != null) {
2068            addDisappearingView(view);
2069        } else if (view.mAttachInfo != null) {
2070           view.dispatchDetachedFromWindow();
2071        }
2072
2073        if (mOnHierarchyChangeListener != null) {
2074            mOnHierarchyChangeListener.onChildViewRemoved(this, view);
2075        }
2076
2077        needGlobalAttributesUpdate(false);
2078
2079        removeFromArray(index);
2080
2081        if (clearChildFocus) {
2082            clearChildFocus(view);
2083        }
2084    }
2085
2086    private void removeViewsInternal(int start, int count) {
2087        final OnHierarchyChangeListener onHierarchyChangeListener = mOnHierarchyChangeListener;
2088        final boolean notifyListener = onHierarchyChangeListener != null;
2089        final View focused = mFocused;
2090        final boolean detach = mAttachInfo != null;
2091        View clearChildFocus = null;
2092
2093        final View[] children = mChildren;
2094        final int end = start + count;
2095
2096        for (int i = start; i < end; i++) {
2097            final View view = children[i];
2098
2099            if (view == focused) {
2100                view.clearFocusForRemoval();
2101                clearChildFocus = view;
2102            }
2103
2104            if (view.getAnimation() != null) {
2105                addDisappearingView(view);
2106            } else if (detach) {
2107               view.dispatchDetachedFromWindow();
2108            }
2109
2110            needGlobalAttributesUpdate(false);
2111
2112            if (notifyListener) {
2113                onHierarchyChangeListener.onChildViewRemoved(this, view);
2114            }
2115        }
2116
2117        removeFromArray(start, count);
2118
2119        if (clearChildFocus != null) {
2120            clearChildFocus(clearChildFocus);
2121        }
2122    }
2123
2124    /**
2125     * Call this method to remove all child views from the
2126     * ViewGroup.
2127     */
2128    public void removeAllViews() {
2129        removeAllViewsInLayout();
2130        requestLayout();
2131        invalidate();
2132    }
2133
2134    /**
2135     * Called by a ViewGroup subclass to remove child views from itself,
2136     * when it must first know its size on screen before it can calculate how many
2137     * child views it will render. An example is a Gallery or a ListView, which
2138     * may "have" 50 children, but actually only render the number of children
2139     * that can currently fit inside the object on screen. Do not call
2140     * this method unless you are extending ViewGroup and understand the
2141     * view measuring and layout pipeline.
2142     */
2143    public void removeAllViewsInLayout() {
2144        final int count = mChildrenCount;
2145        if (count <= 0) {
2146            return;
2147        }
2148
2149        final View[] children = mChildren;
2150        mChildrenCount = 0;
2151
2152        final OnHierarchyChangeListener listener = mOnHierarchyChangeListener;
2153        final boolean notify = listener != null;
2154        final View focused = mFocused;
2155        final boolean detach = mAttachInfo != null;
2156        View clearChildFocus = null;
2157
2158        needGlobalAttributesUpdate(false);
2159
2160        for (int i = count - 1; i >= 0; i--) {
2161            final View view = children[i];
2162
2163            if (view == focused) {
2164                view.clearFocusForRemoval();
2165                clearChildFocus = view;
2166            }
2167
2168            if (view.getAnimation() != null) {
2169                addDisappearingView(view);
2170            } else if (detach) {
2171               view.dispatchDetachedFromWindow();
2172            }
2173
2174            if (notify) {
2175                listener.onChildViewRemoved(this, view);
2176            }
2177
2178            view.mParent = null;
2179            children[i] = null;
2180        }
2181
2182        if (clearChildFocus != null) {
2183            clearChildFocus(clearChildFocus);
2184        }
2185    }
2186
2187    /**
2188     * Finishes the removal of a detached view. This method will dispatch the detached from
2189     * window event and notify the hierarchy change listener.
2190     *
2191     * @param child the child to be definitely removed from the view hierarchy
2192     * @param animate if true and the view has an animation, the view is placed in the
2193     *                disappearing views list, otherwise, it is detached from the window
2194     *
2195     * @see #attachViewToParent(View, int, android.view.ViewGroup.LayoutParams)
2196     * @see #detachAllViewsFromParent()
2197     * @see #detachViewFromParent(View)
2198     * @see #detachViewFromParent(int)
2199     */
2200    protected void removeDetachedView(View child, boolean animate) {
2201        if (child == mFocused) {
2202            child.clearFocus();
2203        }
2204
2205        if (animate && child.getAnimation() != null) {
2206            addDisappearingView(child);
2207        } else if (child.mAttachInfo != null) {
2208            child.dispatchDetachedFromWindow();
2209        }
2210
2211        if (mOnHierarchyChangeListener != null) {
2212            mOnHierarchyChangeListener.onChildViewRemoved(this, child);
2213        }
2214    }
2215
2216    /**
2217     * Attaches a view to this view group. Attaching a view assigns this group as the parent,
2218     * sets the layout parameters and puts the view in the list of children so it can be retrieved
2219     * by calling {@link #getChildAt(int)}.
2220     *
2221     * This method should be called only for view which were detached from their parent.
2222     *
2223     * @param child the child to attach
2224     * @param index the index at which the child should be attached
2225     * @param params the layout parameters of the child
2226     *
2227     * @see #removeDetachedView(View, boolean)
2228     * @see #detachAllViewsFromParent()
2229     * @see #detachViewFromParent(View)
2230     * @see #detachViewFromParent(int)
2231     */
2232    protected void attachViewToParent(View child, int index, LayoutParams params) {
2233        child.mLayoutParams = params;
2234
2235        if (index < 0) {
2236            index = mChildrenCount;
2237        }
2238
2239        addInArray(child, index);
2240
2241        child.mParent = this;
2242        child.mPrivateFlags = (child.mPrivateFlags & ~DIRTY_MASK) | DRAWN;
2243
2244        if (child.hasFocus()) {
2245            requestChildFocus(child, child.findFocus());
2246        }
2247    }
2248
2249    /**
2250     * Detaches a view from its parent. Detaching a view should be temporary and followed
2251     * either by a call to {@link #attachViewToParent(View, int, android.view.ViewGroup.LayoutParams)}
2252     * or a call to {@link #removeDetachedView(View, boolean)}. When a view is detached,
2253     * its parent is null and cannot be retrieved by a call to {@link #getChildAt(int)}.
2254     *
2255     * @param child the child to detach
2256     *
2257     * @see #detachViewFromParent(int)
2258     * @see #detachViewsFromParent(int, int)
2259     * @see #detachAllViewsFromParent()
2260     * @see #attachViewToParent(View, int, android.view.ViewGroup.LayoutParams)
2261     * @see #removeDetachedView(View, boolean)
2262     */
2263    protected void detachViewFromParent(View child) {
2264        removeFromArray(indexOfChild(child));
2265    }
2266
2267    /**
2268     * Detaches a view from its parent. Detaching a view should be temporary and followed
2269     * either by a call to {@link #attachViewToParent(View, int, android.view.ViewGroup.LayoutParams)}
2270     * or a call to {@link #removeDetachedView(View, boolean)}. When a view is detached,
2271     * its parent is null and cannot be retrieved by a call to {@link #getChildAt(int)}.
2272     *
2273     * @param index the index of the child to detach
2274     *
2275     * @see #detachViewFromParent(View)
2276     * @see #detachAllViewsFromParent()
2277     * @see #detachViewsFromParent(int, int)
2278     * @see #attachViewToParent(View, int, android.view.ViewGroup.LayoutParams)
2279     * @see #removeDetachedView(View, boolean)
2280     */
2281    protected void detachViewFromParent(int index) {
2282        removeFromArray(index);
2283    }
2284
2285    /**
2286     * Detaches a range of view from their parent. Detaching a view should be temporary and followed
2287     * either by a call to {@link #attachViewToParent(View, int, android.view.ViewGroup.LayoutParams)}
2288     * or a call to {@link #removeDetachedView(View, boolean)}. When a view is detached, its
2289     * parent is null and cannot be retrieved by a call to {@link #getChildAt(int)}.
2290     *
2291     * @param start the first index of the childrend range to detach
2292     * @param count the number of children to detach
2293     *
2294     * @see #detachViewFromParent(View)
2295     * @see #detachViewFromParent(int)
2296     * @see #detachAllViewsFromParent()
2297     * @see #attachViewToParent(View, int, android.view.ViewGroup.LayoutParams)
2298     * @see #removeDetachedView(View, boolean)
2299     */
2300    protected void detachViewsFromParent(int start, int count) {
2301        removeFromArray(start, count);
2302    }
2303
2304    /**
2305     * Detaches all views from the parent. Detaching a view should be temporary and followed
2306     * either by a call to {@link #attachViewToParent(View, int, android.view.ViewGroup.LayoutParams)}
2307     * or a call to {@link #removeDetachedView(View, boolean)}. When a view is detached,
2308     * its parent is null and cannot be retrieved by a call to {@link #getChildAt(int)}.
2309     *
2310     * @see #detachViewFromParent(View)
2311     * @see #detachViewFromParent(int)
2312     * @see #detachViewsFromParent(int, int)
2313     * @see #attachViewToParent(View, int, android.view.ViewGroup.LayoutParams)
2314     * @see #removeDetachedView(View, boolean)
2315     */
2316    protected void detachAllViewsFromParent() {
2317        final int count = mChildrenCount;
2318        if (count <= 0) {
2319            return;
2320        }
2321
2322        final View[] children = mChildren;
2323        mChildrenCount = 0;
2324
2325        for (int i = count - 1; i >= 0; i--) {
2326            children[i].mParent = null;
2327            children[i] = null;
2328        }
2329    }
2330
2331    /**
2332     * Don't call or override this method. It is used for the implementation of
2333     * the view hierarchy.
2334     */
2335    public final void invalidateChild(View child, final Rect dirty) {
2336        if (ViewDebug.TRACE_HIERARCHY) {
2337            ViewDebug.trace(this, ViewDebug.HierarchyTraceType.INVALIDATE_CHILD);
2338        }
2339
2340        ViewParent parent = this;
2341
2342        final AttachInfo attachInfo = mAttachInfo;
2343        if (attachInfo != null) {
2344            final int[] location = attachInfo.mInvalidateChildLocation;
2345            location[CHILD_LEFT_INDEX] = child.mLeft;
2346            location[CHILD_TOP_INDEX] = child.mTop;
2347
2348            // If the child is drawing an animation, we want to copy this flag onto
2349            // ourselves and the parent to make sure the invalidate request goes
2350            // through
2351            final boolean drawAnimation = (child.mPrivateFlags & DRAW_ANIMATION) == DRAW_ANIMATION;
2352
2353            // Check whether the child that requests the invalidate is fully opaque
2354            final boolean isOpaque = child.isOpaque() && !drawAnimation &&
2355                    child.getAnimation() != null;
2356            // Mark the child as dirty, using the appropriate flag
2357            // Make sure we do not set both flags at the same time
2358            final int opaqueFlag = isOpaque ? DIRTY_OPAQUE : DIRTY;
2359
2360            do {
2361                View view = null;
2362                if (parent instanceof View) {
2363                    view = (View) parent;
2364                }
2365
2366                if (drawAnimation) {
2367                    if (view != null) {
2368                        view.mPrivateFlags |= DRAW_ANIMATION;
2369                    } else if (parent instanceof ViewRoot) {
2370                        ((ViewRoot) parent).mIsAnimating = true;
2371                    }
2372                }
2373
2374                // If the parent is dirty opaque or not dirty, mark it dirty with the opaque
2375                // flag coming from the child that initiated the invalidate
2376                if (view != null && (view.mPrivateFlags & DIRTY_MASK) != DIRTY) {
2377                    view.mPrivateFlags = (view.mPrivateFlags & ~DIRTY_MASK) | opaqueFlag;
2378                }
2379
2380                parent = parent.invalidateChildInParent(location, dirty);
2381            } while (parent != null);
2382        }
2383    }
2384
2385    /**
2386     * Don't call or override this method. It is used for the implementation of
2387     * the view hierarchy.
2388     *
2389     * This implementation returns null if this ViewGroup does not have a parent,
2390     * if this ViewGroup is already fully invalidated or if the dirty rectangle
2391     * does not intersect with this ViewGroup's bounds.
2392     */
2393    public ViewParent invalidateChildInParent(final int[] location, final Rect dirty) {
2394        if (ViewDebug.TRACE_HIERARCHY) {
2395            ViewDebug.trace(this, ViewDebug.HierarchyTraceType.INVALIDATE_CHILD_IN_PARENT);
2396        }
2397
2398        if ((mPrivateFlags & DRAWN) == DRAWN) {
2399            if ((mGroupFlags & (FLAG_OPTIMIZE_INVALIDATE | FLAG_ANIMATION_DONE)) !=
2400                        FLAG_OPTIMIZE_INVALIDATE) {
2401                dirty.offset(location[CHILD_LEFT_INDEX] - mScrollX,
2402                        location[CHILD_TOP_INDEX] - mScrollY);
2403
2404                final int left = mLeft;
2405                final int top = mTop;
2406
2407                if (dirty.intersect(0, 0, mRight - left, mBottom - top) ||
2408                        (mPrivateFlags & DRAW_ANIMATION) == DRAW_ANIMATION) {
2409                    mPrivateFlags &= ~DRAWING_CACHE_VALID;
2410
2411                    location[CHILD_LEFT_INDEX] = left;
2412                    location[CHILD_TOP_INDEX] = top;
2413
2414                    return mParent;
2415                }
2416            } else {
2417                mPrivateFlags &= ~DRAWN & ~DRAWING_CACHE_VALID;
2418
2419                location[CHILD_LEFT_INDEX] = mLeft;
2420                location[CHILD_TOP_INDEX] = mTop;
2421
2422                dirty.set(0, 0, mRight - location[CHILD_LEFT_INDEX],
2423                        mBottom - location[CHILD_TOP_INDEX]);
2424
2425                return mParent;
2426            }
2427        }
2428
2429        return null;
2430    }
2431
2432    /**
2433     * Offset a rectangle that is in a descendant's coordinate
2434     * space into our coordinate space.
2435     * @param descendant A descendant of this view
2436     * @param rect A rectangle defined in descendant's coordinate space.
2437     */
2438    public final void offsetDescendantRectToMyCoords(View descendant, Rect rect) {
2439        offsetRectBetweenParentAndChild(descendant, rect, true, false);
2440    }
2441
2442    /**
2443     * Offset a rectangle that is in our coordinate space into an ancestor's
2444     * coordinate space.
2445     * @param descendant A descendant of this view
2446     * @param rect A rectangle defined in descendant's coordinate space.
2447     */
2448    public final void offsetRectIntoDescendantCoords(View descendant, Rect rect) {
2449        offsetRectBetweenParentAndChild(descendant, rect, false, false);
2450    }
2451
2452    /**
2453     * Helper method that offsets a rect either from parent to descendant or
2454     * descendant to parent.
2455     */
2456    void offsetRectBetweenParentAndChild(View descendant, Rect rect,
2457            boolean offsetFromChildToParent, boolean clipToBounds) {
2458
2459        // already in the same coord system :)
2460        if (descendant == this) {
2461            return;
2462        }
2463
2464        ViewParent theParent = descendant.mParent;
2465
2466        // search and offset up to the parent
2467        while ((theParent != null)
2468                && (theParent instanceof View)
2469                && (theParent != this)) {
2470
2471            if (offsetFromChildToParent) {
2472                rect.offset(descendant.mLeft - descendant.mScrollX,
2473                        descendant.mTop - descendant.mScrollY);
2474                if (clipToBounds) {
2475                    View p = (View) theParent;
2476                    rect.intersect(0, 0, p.mRight - p.mLeft, p.mBottom - p.mTop);
2477                }
2478            } else {
2479                if (clipToBounds) {
2480                    View p = (View) theParent;
2481                    rect.intersect(0, 0, p.mRight - p.mLeft, p.mBottom - p.mTop);
2482                }
2483                rect.offset(descendant.mScrollX - descendant.mLeft,
2484                        descendant.mScrollY - descendant.mTop);
2485            }
2486
2487            descendant = (View) theParent;
2488            theParent = descendant.mParent;
2489        }
2490
2491        // now that we are up to this view, need to offset one more time
2492        // to get into our coordinate space
2493        if (theParent == this) {
2494            if (offsetFromChildToParent) {
2495                rect.offset(descendant.mLeft - descendant.mScrollX,
2496                        descendant.mTop - descendant.mScrollY);
2497            } else {
2498                rect.offset(descendant.mScrollX - descendant.mLeft,
2499                        descendant.mScrollY - descendant.mTop);
2500            }
2501        } else {
2502            throw new IllegalArgumentException("parameter must be a descendant of this view");
2503        }
2504    }
2505
2506    /**
2507     * Offset the vertical location of all children of this view by the specified number of pixels.
2508     *
2509     * @param offset the number of pixels to offset
2510     *
2511     * @hide
2512     */
2513    public void offsetChildrenTopAndBottom(int offset) {
2514        final int count = mChildrenCount;
2515        final View[] children = mChildren;
2516
2517        for (int i = 0; i < count; i++) {
2518            final View v = children[i];
2519            v.mTop += offset;
2520            v.mBottom += offset;
2521        }
2522    }
2523
2524    /**
2525     * {@inheritDoc}
2526     */
2527    public boolean getChildVisibleRect(View child, Rect r, android.graphics.Point offset) {
2528        int dx = child.mLeft - mScrollX;
2529        int dy = child.mTop - mScrollY;
2530        if (offset != null) {
2531            offset.x += dx;
2532            offset.y += dy;
2533        }
2534        r.offset(dx, dy);
2535        return r.intersect(0, 0, mRight - mLeft, mBottom - mTop) &&
2536               (mParent == null || mParent.getChildVisibleRect(this, r, offset));
2537    }
2538
2539    /**
2540     * {@inheritDoc}
2541     */
2542    @Override
2543    protected abstract void onLayout(boolean changed,
2544            int l, int t, int r, int b);
2545
2546    /**
2547     * Indicates whether the view group has the ability to animate its children
2548     * after the first layout.
2549     *
2550     * @return true if the children can be animated, false otherwise
2551     */
2552    protected boolean canAnimate() {
2553        return mLayoutAnimationController != null;
2554    }
2555
2556    /**
2557     * Runs the layout animation. Calling this method triggers a relayout of
2558     * this view group.
2559     */
2560    public void startLayoutAnimation() {
2561        if (mLayoutAnimationController != null) {
2562            mGroupFlags |= FLAG_RUN_ANIMATION;
2563            requestLayout();
2564        }
2565    }
2566
2567    /**
2568     * Schedules the layout animation to be played after the next layout pass
2569     * of this view group. This can be used to restart the layout animation
2570     * when the content of the view group changes or when the activity is
2571     * paused and resumed.
2572     */
2573    public void scheduleLayoutAnimation() {
2574        mGroupFlags |= FLAG_RUN_ANIMATION;
2575    }
2576
2577    /**
2578     * Sets the layout animation controller used to animate the group's
2579     * children after the first layout.
2580     *
2581     * @param controller the animation controller
2582     */
2583    public void setLayoutAnimation(LayoutAnimationController controller) {
2584        mLayoutAnimationController = controller;
2585        if (mLayoutAnimationController != null) {
2586            mGroupFlags |= FLAG_RUN_ANIMATION;
2587        }
2588    }
2589
2590    /**
2591     * Returns the layout animation controller used to animate the group's
2592     * children.
2593     *
2594     * @return the current animation controller
2595     */
2596    public LayoutAnimationController getLayoutAnimation() {
2597        return mLayoutAnimationController;
2598    }
2599
2600    /**
2601     * Indicates whether the children's drawing cache is used during a layout
2602     * animation. By default, the drawing cache is enabled but this will prevent
2603     * nested layout animations from working. To nest animations, you must disable
2604     * the cache.
2605     *
2606     * @return true if the animation cache is enabled, false otherwise
2607     *
2608     * @see #setAnimationCacheEnabled(boolean)
2609     * @see View#setDrawingCacheEnabled(boolean)
2610     */
2611    @ViewDebug.ExportedProperty
2612    public boolean isAnimationCacheEnabled() {
2613        return (mGroupFlags & FLAG_ANIMATION_CACHE) == FLAG_ANIMATION_CACHE;
2614    }
2615
2616    /**
2617     * Enables or disables the children's drawing cache during a layout animation.
2618     * By default, the drawing cache is enabled but this will prevent nested
2619     * layout animations from working. To nest animations, you must disable the
2620     * cache.
2621     *
2622     * @param enabled true to enable the animation cache, false otherwise
2623     *
2624     * @see #isAnimationCacheEnabled()
2625     * @see View#setDrawingCacheEnabled(boolean)
2626     */
2627    public void setAnimationCacheEnabled(boolean enabled) {
2628        setBooleanFlag(FLAG_ANIMATION_CACHE, enabled);
2629    }
2630
2631    /**
2632     * Indicates whether this ViewGroup will always try to draw its children using their
2633     * drawing cache. By default this property is enabled.
2634     *
2635     * @return true if the animation cache is enabled, false otherwise
2636     *
2637     * @see #setAlwaysDrawnWithCacheEnabled(boolean)
2638     * @see #setChildrenDrawnWithCacheEnabled(boolean)
2639     * @see View#setDrawingCacheEnabled(boolean)
2640     */
2641    @ViewDebug.ExportedProperty
2642    public boolean isAlwaysDrawnWithCacheEnabled() {
2643        return (mGroupFlags & FLAG_ALWAYS_DRAWN_WITH_CACHE) == FLAG_ALWAYS_DRAWN_WITH_CACHE;
2644    }
2645
2646    /**
2647     * Indicates whether this ViewGroup will always try to draw its children using their
2648     * drawing cache. This property can be set to true when the cache rendering is
2649     * slightly different from the children's normal rendering. Renderings can be different,
2650     * for instance, when the cache's quality is set to low.
2651     *
2652     * When this property is disabled, the ViewGroup will use the drawing cache of its
2653     * children only when asked to. It's usually the task of subclasses to tell ViewGroup
2654     * when to start using the drawing cache and when to stop using it.
2655     *
2656     * @param always true to always draw with the drawing cache, false otherwise
2657     *
2658     * @see #isAlwaysDrawnWithCacheEnabled()
2659     * @see #setChildrenDrawnWithCacheEnabled(boolean)
2660     * @see View#setDrawingCacheEnabled(boolean)
2661     * @see View#setDrawingCacheQuality(int)
2662     */
2663    public void setAlwaysDrawnWithCacheEnabled(boolean always) {
2664        setBooleanFlag(FLAG_ALWAYS_DRAWN_WITH_CACHE, always);
2665    }
2666
2667    /**
2668     * Indicates whether the ViewGroup is currently drawing its children using
2669     * their drawing cache.
2670     *
2671     * @return true if children should be drawn with their cache, false otherwise
2672     *
2673     * @see #setAlwaysDrawnWithCacheEnabled(boolean)
2674     * @see #setChildrenDrawnWithCacheEnabled(boolean)
2675     */
2676    @ViewDebug.ExportedProperty
2677    protected boolean isChildrenDrawnWithCacheEnabled() {
2678        return (mGroupFlags & FLAG_CHILDREN_DRAWN_WITH_CACHE) == FLAG_CHILDREN_DRAWN_WITH_CACHE;
2679    }
2680
2681    /**
2682     * Tells the ViewGroup to draw its children using their drawing cache. This property
2683     * is ignored when {@link #isAlwaysDrawnWithCacheEnabled()} is true. A child's drawing cache
2684     * will be used only if it has been enabled.
2685     *
2686     * Subclasses should call this method to start and stop using the drawing cache when
2687     * they perform performance sensitive operations, like scrolling or animating.
2688     *
2689     * @param enabled true if children should be drawn with their cache, false otherwise
2690     *
2691     * @see #setAlwaysDrawnWithCacheEnabled(boolean)
2692     * @see #isChildrenDrawnWithCacheEnabled()
2693     */
2694    protected void setChildrenDrawnWithCacheEnabled(boolean enabled) {
2695        setBooleanFlag(FLAG_CHILDREN_DRAWN_WITH_CACHE, enabled);
2696    }
2697
2698    private void setBooleanFlag(int flag, boolean value) {
2699        if (value) {
2700            mGroupFlags |= flag;
2701        } else {
2702            mGroupFlags &= ~flag;
2703        }
2704    }
2705
2706    /**
2707     * Returns an integer indicating what types of drawing caches are kept in memory.
2708     *
2709     * @see #setPersistentDrawingCache(int)
2710     * @see #setAnimationCacheEnabled(boolean)
2711     *
2712     * @return one or a combination of {@link #PERSISTENT_NO_CACHE},
2713     *         {@link #PERSISTENT_ANIMATION_CACHE}, {@link #PERSISTENT_SCROLLING_CACHE}
2714     *         and {@link #PERSISTENT_ALL_CACHES}
2715     */
2716    @ViewDebug.ExportedProperty(mapping = {
2717        @ViewDebug.IntToString(from = PERSISTENT_NO_CACHE,        to = "NONE"),
2718        @ViewDebug.IntToString(from = PERSISTENT_ALL_CACHES,      to = "ANIMATION"),
2719        @ViewDebug.IntToString(from = PERSISTENT_SCROLLING_CACHE, to = "SCROLLING"),
2720        @ViewDebug.IntToString(from = PERSISTENT_ALL_CACHES,      to = "ALL")
2721    })
2722    public int getPersistentDrawingCache() {
2723        return mPersistentDrawingCache;
2724    }
2725
2726    /**
2727     * Indicates what types of drawing caches should be kept in memory after
2728     * they have been created.
2729     *
2730     * @see #getPersistentDrawingCache()
2731     * @see #setAnimationCacheEnabled(boolean)
2732     *
2733     * @param drawingCacheToKeep one or a combination of {@link #PERSISTENT_NO_CACHE},
2734     *        {@link #PERSISTENT_ANIMATION_CACHE}, {@link #PERSISTENT_SCROLLING_CACHE}
2735     *        and {@link #PERSISTENT_ALL_CACHES}
2736     */
2737    public void setPersistentDrawingCache(int drawingCacheToKeep) {
2738        mPersistentDrawingCache = drawingCacheToKeep & PERSISTENT_ALL_CACHES;
2739    }
2740
2741    /**
2742     * Returns a new set of layout parameters based on the supplied attributes set.
2743     *
2744     * @param attrs the attributes to build the layout parameters from
2745     *
2746     * @return an instance of {@link android.view.ViewGroup.LayoutParams} or one
2747     *         of its descendants
2748     */
2749    public LayoutParams generateLayoutParams(AttributeSet attrs) {
2750        return new LayoutParams(getContext(), attrs);
2751    }
2752
2753    /**
2754     * Returns a safe set of layout parameters based on the supplied layout params.
2755     * When a ViewGroup is passed a View whose layout params do not pass the test of
2756     * {@link #checkLayoutParams(android.view.ViewGroup.LayoutParams)}, this method
2757     * is invoked. This method should return a new set of layout params suitable for
2758     * this ViewGroup, possibly by copying the appropriate attributes from the
2759     * specified set of layout params.
2760     *
2761     * @param p The layout parameters to convert into a suitable set of layout parameters
2762     *          for this ViewGroup.
2763     *
2764     * @return an instance of {@link android.view.ViewGroup.LayoutParams} or one
2765     *         of its descendants
2766     */
2767    protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
2768        return p;
2769    }
2770
2771    /**
2772     * Returns a set of default layout parameters. These parameters are requested
2773     * when the View passed to {@link #addView(View)} has no layout parameters
2774     * already set. If null is returned, an exception is thrown from addView.
2775     *
2776     * @return a set of default layout parameters or null
2777     */
2778    protected LayoutParams generateDefaultLayoutParams() {
2779        return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
2780    }
2781
2782    /**
2783     * @hide
2784     */
2785    @Override
2786    protected boolean dispatchConsistencyCheck(int consistency) {
2787        boolean result = super.dispatchConsistencyCheck(consistency);
2788
2789        final int count = mChildrenCount;
2790        final View[] children = mChildren;
2791        for (int i = 0; i < count; i++) {
2792            if (!children[i].dispatchConsistencyCheck(consistency)) result = false;
2793        }
2794
2795        return result;
2796    }
2797
2798    /**
2799     * @hide
2800     */
2801    @Override
2802    protected boolean onConsistencyCheck(int consistency) {
2803        boolean result = super.onConsistencyCheck(consistency);
2804
2805        final boolean checkLayout = (consistency & ViewDebug.CONSISTENCY_LAYOUT) != 0;
2806        final boolean checkDrawing = (consistency & ViewDebug.CONSISTENCY_DRAWING) != 0;
2807
2808        if (checkLayout) {
2809            final int count = mChildrenCount;
2810            final View[] children = mChildren;
2811            for (int i = 0; i < count; i++) {
2812                if (children[i].getParent() != this) {
2813                    result = false;
2814                    android.util.Log.d(ViewDebug.CONSISTENCY_LOG_TAG,
2815                            "View " + children[i] + " has no parent/a parent that is not " + this);
2816                }
2817            }
2818        }
2819
2820        if (checkDrawing) {
2821            // If this group is dirty, check that the parent is dirty as well
2822            if ((mPrivateFlags & DIRTY_MASK) != 0) {
2823                final ViewParent parent = getParent();
2824                if (parent != null && !(parent instanceof ViewRoot)) {
2825                    if ((((View) parent).mPrivateFlags & DIRTY_MASK) == 0) {
2826                        result = false;
2827                        android.util.Log.d(ViewDebug.CONSISTENCY_LOG_TAG,
2828                                "ViewGroup " + this + " is dirty but its parent is not: " + this);
2829                    }
2830                }
2831            }
2832        }
2833
2834        return result;
2835    }
2836
2837    /**
2838     * {@inheritDoc}
2839     */
2840    @Override
2841    protected void debug(int depth) {
2842        super.debug(depth);
2843        String output;
2844
2845        if (mFocused != null) {
2846            output = debugIndent(depth);
2847            output += "mFocused";
2848            Log.d(VIEW_LOG_TAG, output);
2849        }
2850        if (mChildrenCount != 0) {
2851            output = debugIndent(depth);
2852            output += "{";
2853            Log.d(VIEW_LOG_TAG, output);
2854        }
2855        int count = mChildrenCount;
2856        for (int i = 0; i < count; i++) {
2857            View child = mChildren[i];
2858            child.debug(depth + 1);
2859        }
2860
2861        if (mChildrenCount != 0) {
2862            output = debugIndent(depth);
2863            output += "}";
2864            Log.d(VIEW_LOG_TAG, output);
2865        }
2866    }
2867
2868    /**
2869     * Returns the position in the group of the specified child view.
2870     *
2871     * @param child the view for which to get the position
2872     * @return a positive integer representing the position of the view in the
2873     *         group, or -1 if the view does not exist in the group
2874     */
2875    public int indexOfChild(View child) {
2876        final int count = mChildrenCount;
2877        final View[] children = mChildren;
2878        for (int i = 0; i < count; i++) {
2879            if (children[i] == child) {
2880                return i;
2881            }
2882        }
2883        return -1;
2884    }
2885
2886    /**
2887     * Returns the number of children in the group.
2888     *
2889     * @return a positive integer representing the number of children in
2890     *         the group
2891     */
2892    public int getChildCount() {
2893        return mChildrenCount;
2894    }
2895
2896    /**
2897     * Returns the view at the specified position in the group.
2898     *
2899     * @param index the position at which to get the view from
2900     * @return the view at the specified position or null if the position
2901     *         does not exist within the group
2902     */
2903    public View getChildAt(int index) {
2904        try {
2905            return mChildren[index];
2906        } catch (IndexOutOfBoundsException ex) {
2907            return null;
2908        }
2909    }
2910
2911    /**
2912     * Ask all of the children of this view to measure themselves, taking into
2913     * account both the MeasureSpec requirements for this view and its padding.
2914     * We skip children that are in the GONE state The heavy lifting is done in
2915     * getChildMeasureSpec.
2916     *
2917     * @param widthMeasureSpec The width requirements for this view
2918     * @param heightMeasureSpec The height requirements for this view
2919     */
2920    protected void measureChildren(int widthMeasureSpec, int heightMeasureSpec) {
2921        final int size = mChildrenCount;
2922        final View[] children = mChildren;
2923        for (int i = 0; i < size; ++i) {
2924            final View child = children[i];
2925            if ((child.mViewFlags & VISIBILITY_MASK) != GONE) {
2926                measureChild(child, widthMeasureSpec, heightMeasureSpec);
2927            }
2928        }
2929    }
2930
2931    /**
2932     * Ask one of the children of this view to measure itself, taking into
2933     * account both the MeasureSpec requirements for this view and its padding.
2934     * The heavy lifting is done in getChildMeasureSpec.
2935     *
2936     * @param child The child to measure
2937     * @param parentWidthMeasureSpec The width requirements for this view
2938     * @param parentHeightMeasureSpec The height requirements for this view
2939     */
2940    protected void measureChild(View child, int parentWidthMeasureSpec,
2941            int parentHeightMeasureSpec) {
2942        final LayoutParams lp = child.getLayoutParams();
2943
2944        final int childWidthMeasureSpec = getChildMeasureSpec(parentWidthMeasureSpec,
2945                mPaddingLeft + mPaddingRight, lp.width);
2946        final int childHeightMeasureSpec = getChildMeasureSpec(parentHeightMeasureSpec,
2947                mPaddingTop + mPaddingBottom, lp.height);
2948
2949        child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
2950    }
2951
2952    /**
2953     * Ask one of the children of this view to measure itself, taking into
2954     * account both the MeasureSpec requirements for this view and its padding
2955     * and margins. The child must have MarginLayoutParams The heavy lifting is
2956     * done in getChildMeasureSpec.
2957     *
2958     * @param child The child to measure
2959     * @param parentWidthMeasureSpec The width requirements for this view
2960     * @param widthUsed Extra space that has been used up by the parent
2961     *        horizontally (possibly by other children of the parent)
2962     * @param parentHeightMeasureSpec The height requirements for this view
2963     * @param heightUsed Extra space that has been used up by the parent
2964     *        vertically (possibly by other children of the parent)
2965     */
2966    protected void measureChildWithMargins(View child,
2967            int parentWidthMeasureSpec, int widthUsed,
2968            int parentHeightMeasureSpec, int heightUsed) {
2969        final MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
2970
2971        final int childWidthMeasureSpec = getChildMeasureSpec(parentWidthMeasureSpec,
2972                mPaddingLeft + mPaddingRight + lp.leftMargin + lp.rightMargin
2973                        + widthUsed, lp.width);
2974        final int childHeightMeasureSpec = getChildMeasureSpec(parentHeightMeasureSpec,
2975                mPaddingTop + mPaddingBottom + lp.topMargin + lp.bottomMargin
2976                        + heightUsed, lp.height);
2977
2978        child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
2979    }
2980
2981    /**
2982     * Does the hard part of measureChildren: figuring out the MeasureSpec to
2983     * pass to a particular child. This method figures out the right MeasureSpec
2984     * for one dimension (height or width) of one child view.
2985     *
2986     * The goal is to combine information from our MeasureSpec with the
2987     * LayoutParams of the child to get the best possible results. For example,
2988     * if the this view knows its size (because its MeasureSpec has a mode of
2989     * EXACTLY), and the child has indicated in its LayoutParams that it wants
2990     * to be the same size as the parent, the parent should ask the child to
2991     * layout given an exact size.
2992     *
2993     * @param spec The requirements for this view
2994     * @param padding The padding of this view for the current dimension and
2995     *        margins, if applicable
2996     * @param childDimension How big the child wants to be in the current
2997     *        dimension
2998     * @return a MeasureSpec integer for the child
2999     */
3000    public static int getChildMeasureSpec(int spec, int padding, int childDimension) {
3001        int specMode = MeasureSpec.getMode(spec);
3002        int specSize = MeasureSpec.getSize(spec);
3003
3004        int size = Math.max(0, specSize - padding);
3005
3006        int resultSize = 0;
3007        int resultMode = 0;
3008
3009        switch (specMode) {
3010        // Parent has imposed an exact size on us
3011        case MeasureSpec.EXACTLY:
3012            if (childDimension >= 0) {
3013                resultSize = childDimension;
3014                resultMode = MeasureSpec.EXACTLY;
3015            } else if (childDimension == LayoutParams.FILL_PARENT) {
3016                // Child wants to be our size. So be it.
3017                resultSize = size;
3018                resultMode = MeasureSpec.EXACTLY;
3019            } else if (childDimension == LayoutParams.WRAP_CONTENT) {
3020                // Child wants to determine its own size. It can't be
3021                // bigger than us.
3022                resultSize = size;
3023                resultMode = MeasureSpec.AT_MOST;
3024            }
3025            break;
3026
3027        // Parent has imposed a maximum size on us
3028        case MeasureSpec.AT_MOST:
3029            if (childDimension >= 0) {
3030                // Child wants a specific size... so be it
3031                resultSize = childDimension;
3032                resultMode = MeasureSpec.EXACTLY;
3033            } else if (childDimension == LayoutParams.FILL_PARENT) {
3034                // Child wants to be our size, but our size is not fixed.
3035                // Constrain child to not be bigger than us.
3036                resultSize = size;
3037                resultMode = MeasureSpec.AT_MOST;
3038            } else if (childDimension == LayoutParams.WRAP_CONTENT) {
3039                // Child wants to determine its own size. It can't be
3040                // bigger than us.
3041                resultSize = size;
3042                resultMode = MeasureSpec.AT_MOST;
3043            }
3044            break;
3045
3046        // Parent asked to see how big we want to be
3047        case MeasureSpec.UNSPECIFIED:
3048            if (childDimension >= 0) {
3049                // Child wants a specific size... let him have it
3050                resultSize = childDimension;
3051                resultMode = MeasureSpec.EXACTLY;
3052            } else if (childDimension == LayoutParams.FILL_PARENT) {
3053                // Child wants to be our size... find out how big it should
3054                // be
3055                resultSize = 0;
3056                resultMode = MeasureSpec.UNSPECIFIED;
3057            } else if (childDimension == LayoutParams.WRAP_CONTENT) {
3058                // Child wants to determine its own size.... find out how
3059                // big it should be
3060                resultSize = 0;
3061                resultMode = MeasureSpec.UNSPECIFIED;
3062            }
3063            break;
3064        }
3065        return MeasureSpec.makeMeasureSpec(resultSize, resultMode);
3066    }
3067
3068
3069    /**
3070     * Removes any pending animations for views that have been removed. Call
3071     * this if you don't want animations for exiting views to stack up.
3072     */
3073    public void clearDisappearingChildren() {
3074        if (mDisappearingChildren != null) {
3075            mDisappearingChildren.clear();
3076        }
3077    }
3078
3079    /**
3080     * Add a view which is removed from mChildren but still needs animation
3081     *
3082     * @param v View to add
3083     */
3084    private void addDisappearingView(View v) {
3085        ArrayList<View> disappearingChildren = mDisappearingChildren;
3086
3087        if (disappearingChildren == null) {
3088            disappearingChildren = mDisappearingChildren = new ArrayList<View>();
3089        }
3090
3091        disappearingChildren.add(v);
3092    }
3093
3094    /**
3095     * Cleanup a view when its animation is done. This may mean removing it from
3096     * the list of disappearing views.
3097     *
3098     * @param view The view whose animation has finished
3099     * @param animation The animation, cannot be null
3100     */
3101    private void finishAnimatingView(final View view, Animation animation) {
3102        final ArrayList<View> disappearingChildren = mDisappearingChildren;
3103        if (disappearingChildren != null) {
3104            if (disappearingChildren.contains(view)) {
3105                disappearingChildren.remove(view);
3106
3107                if (view.mAttachInfo != null) {
3108                    view.dispatchDetachedFromWindow();
3109                }
3110
3111                view.clearAnimation();
3112                mGroupFlags |= FLAG_INVALIDATE_REQUIRED;
3113            }
3114        }
3115
3116        if (animation != null && !animation.getFillAfter()) {
3117            view.clearAnimation();
3118        }
3119
3120        if ((view.mPrivateFlags & ANIMATION_STARTED) == ANIMATION_STARTED) {
3121            view.onAnimationEnd();
3122            // Should be performed by onAnimationEnd() but this avoid an infinite loop,
3123            // so we'd rather be safe than sorry
3124            view.mPrivateFlags &= ~ANIMATION_STARTED;
3125            // Draw one more frame after the animation is done
3126            mGroupFlags |= FLAG_INVALIDATE_REQUIRED;
3127        }
3128    }
3129
3130    /**
3131     * {@inheritDoc}
3132     */
3133    @Override
3134    public boolean gatherTransparentRegion(Region region) {
3135        // If no transparent regions requested, we are always opaque.
3136        final boolean meOpaque = (mPrivateFlags & View.REQUEST_TRANSPARENT_REGIONS) == 0;
3137        if (meOpaque && region == null) {
3138            // The caller doesn't care about the region, so stop now.
3139            return true;
3140        }
3141        super.gatherTransparentRegion(region);
3142        final View[] children = mChildren;
3143        final int count = mChildrenCount;
3144        boolean noneOfTheChildrenAreTransparent = true;
3145        for (int i = 0; i < count; i++) {
3146            final View child = children[i];
3147            if ((child.mViewFlags & VISIBILITY_MASK) != GONE || child.getAnimation() != null) {
3148                if (!child.gatherTransparentRegion(region)) {
3149                    noneOfTheChildrenAreTransparent = false;
3150                }
3151            }
3152        }
3153        return meOpaque || noneOfTheChildrenAreTransparent;
3154    }
3155
3156    /**
3157     * {@inheritDoc}
3158     */
3159    public void requestTransparentRegion(View child) {
3160        if (child != null) {
3161            child.mPrivateFlags |= View.REQUEST_TRANSPARENT_REGIONS;
3162            if (mParent != null) {
3163                mParent.requestTransparentRegion(this);
3164            }
3165        }
3166    }
3167
3168
3169    @Override
3170    protected boolean fitSystemWindows(Rect insets) {
3171        boolean done = super.fitSystemWindows(insets);
3172        if (!done) {
3173            final int count = mChildrenCount;
3174            final View[] children = mChildren;
3175            for (int i = 0; i < count; i++) {
3176                done = children[i].fitSystemWindows(insets);
3177                if (done) {
3178                    break;
3179                }
3180            }
3181        }
3182        return done;
3183    }
3184
3185    /**
3186     * Returns the animation listener to which layout animation events are
3187     * sent.
3188     *
3189     * @return an {@link android.view.animation.Animation.AnimationListener}
3190     */
3191    public Animation.AnimationListener getLayoutAnimationListener() {
3192        return mAnimationListener;
3193    }
3194
3195    @Override
3196    protected void drawableStateChanged() {
3197        super.drawableStateChanged();
3198
3199        if ((mGroupFlags & FLAG_NOTIFY_CHILDREN_ON_DRAWABLE_STATE_CHANGE) != 0) {
3200            if ((mGroupFlags & FLAG_ADD_STATES_FROM_CHILDREN) != 0) {
3201                throw new IllegalStateException("addStateFromChildren cannot be enabled if a"
3202                        + " child has duplicateParentState set to true");
3203            }
3204
3205            final View[] children = mChildren;
3206            final int count = mChildrenCount;
3207
3208            for (int i = 0; i < count; i++) {
3209                final View child = children[i];
3210                if ((child.mViewFlags & DUPLICATE_PARENT_STATE) != 0) {
3211                    child.refreshDrawableState();
3212                }
3213            }
3214        }
3215    }
3216
3217    @Override
3218    protected int[] onCreateDrawableState(int extraSpace) {
3219        if ((mGroupFlags & FLAG_ADD_STATES_FROM_CHILDREN) == 0) {
3220            return super.onCreateDrawableState(extraSpace);
3221        }
3222
3223        int need = 0;
3224        int n = getChildCount();
3225        for (int i = 0; i < n; i++) {
3226            int[] childState = getChildAt(i).getDrawableState();
3227
3228            if (childState != null) {
3229                need += childState.length;
3230            }
3231        }
3232
3233        int[] state = super.onCreateDrawableState(extraSpace + need);
3234
3235        for (int i = 0; i < n; i++) {
3236            int[] childState = getChildAt(i).getDrawableState();
3237
3238            if (childState != null) {
3239                state = mergeDrawableStates(state, childState);
3240            }
3241        }
3242
3243        return state;
3244    }
3245
3246    /**
3247     * Sets whether this ViewGroup's drawable states also include
3248     * its children's drawable states.  This is used, for example, to
3249     * make a group appear to be focused when its child EditText or button
3250     * is focused.
3251     */
3252    public void setAddStatesFromChildren(boolean addsStates) {
3253        if (addsStates) {
3254            mGroupFlags |= FLAG_ADD_STATES_FROM_CHILDREN;
3255        } else {
3256            mGroupFlags &= ~FLAG_ADD_STATES_FROM_CHILDREN;
3257        }
3258
3259        refreshDrawableState();
3260    }
3261
3262    /**
3263     * Returns whether this ViewGroup's drawable states also include
3264     * its children's drawable states.  This is used, for example, to
3265     * make a group appear to be focused when its child EditText or button
3266     * is focused.
3267     */
3268    public boolean addStatesFromChildren() {
3269        return (mGroupFlags & FLAG_ADD_STATES_FROM_CHILDREN) != 0;
3270    }
3271
3272    /**
3273     * If {link #addStatesFromChildren} is true, refreshes this group's
3274     * drawable state (to include the states from its children).
3275     */
3276    public void childDrawableStateChanged(View child) {
3277        if ((mGroupFlags & FLAG_ADD_STATES_FROM_CHILDREN) != 0) {
3278            refreshDrawableState();
3279        }
3280    }
3281
3282    /**
3283     * Specifies the animation listener to which layout animation events must
3284     * be sent. Only
3285     * {@link android.view.animation.Animation.AnimationListener#onAnimationStart(Animation)}
3286     * and
3287     * {@link android.view.animation.Animation.AnimationListener#onAnimationEnd(Animation)}
3288     * are invoked.
3289     *
3290     * @param animationListener the layout animation listener
3291     */
3292    public void setLayoutAnimationListener(Animation.AnimationListener animationListener) {
3293        mAnimationListener = animationListener;
3294    }
3295
3296    /**
3297     * LayoutParams are used by views to tell their parents how they want to be
3298     * laid out. See
3299     * {@link android.R.styleable#ViewGroup_Layout ViewGroup Layout Attributes}
3300     * for a list of all child view attributes that this class supports.
3301     *
3302     * <p>
3303     * The base LayoutParams class just describes how big the view wants to be
3304     * for both width and height. For each dimension, it can specify one of:
3305     * <ul>
3306     * <li> an exact number
3307     * <li>FILL_PARENT, which means the view wants to be as big as its parent
3308     * (minus padding)
3309     * <li> WRAP_CONTENT, which means that the view wants to be just big enough
3310     * to enclose its content (plus padding)
3311     * </ul>
3312     * There are subclasses of LayoutParams for different subclasses of
3313     * ViewGroup. For example, AbsoluteLayout has its own subclass of
3314     * LayoutParams which adds an X and Y value.
3315     *
3316     * @attr ref android.R.styleable#ViewGroup_Layout_layout_height
3317     * @attr ref android.R.styleable#ViewGroup_Layout_layout_width
3318     */
3319    public static class LayoutParams {
3320        /**
3321         * Special value for the height or width requested by a View.
3322         * FILL_PARENT means that the view wants to fill the available space
3323         * within the parent, taking the parent's padding into account.
3324         */
3325        public static final int FILL_PARENT = -1;
3326
3327        /**
3328         * Special value for the height or width requested by a View.
3329         * WRAP_CONTENT means that the view wants to be just large enough to fit
3330         * its own internal content, taking its own padding into account.
3331         */
3332        public static final int WRAP_CONTENT = -2;
3333
3334        /**
3335         * Information about how wide the view wants to be. Can be an exact
3336         * size, or one of the constants FILL_PARENT or WRAP_CONTENT.
3337         */
3338        @ViewDebug.ExportedProperty(mapping = {
3339            @ViewDebug.IntToString(from = FILL_PARENT, to = "FILL_PARENT"),
3340            @ViewDebug.IntToString(from = WRAP_CONTENT, to = "WRAP_CONTENT")
3341        })
3342        public int width;
3343
3344        /**
3345         * Information about how tall the view wants to be. Can be an exact
3346         * size, or one of the constants FILL_PARENT or WRAP_CONTENT.
3347         */
3348        @ViewDebug.ExportedProperty(mapping = {
3349            @ViewDebug.IntToString(from = FILL_PARENT, to = "FILL_PARENT"),
3350            @ViewDebug.IntToString(from = WRAP_CONTENT, to = "WRAP_CONTENT")
3351        })
3352        public int height;
3353
3354        /**
3355         * Used to animate layouts.
3356         */
3357        public LayoutAnimationController.AnimationParameters layoutAnimationParameters;
3358
3359        /**
3360         * Creates a new set of layout parameters. The values are extracted from
3361         * the supplied attributes set and context. The XML attributes mapped
3362         * to this set of layout parameters are:
3363         *
3364         * <ul>
3365         *   <li><code>layout_width</code>: the width, either an exact value,
3366         *   {@link #WRAP_CONTENT} or {@link #FILL_PARENT}</li>
3367         *   <li><code>layout_height</code>: the height, either an exact value,
3368         *   {@link #WRAP_CONTENT} or {@link #FILL_PARENT}</li>
3369         * </ul>
3370         *
3371         * @param c the application environment
3372         * @param attrs the set of attributes from which to extract the layout
3373         *              parameters' values
3374         */
3375        public LayoutParams(Context c, AttributeSet attrs) {
3376            TypedArray a = c.obtainStyledAttributes(attrs, R.styleable.ViewGroup_Layout);
3377            setBaseAttributes(a,
3378                    R.styleable.ViewGroup_Layout_layout_width,
3379                    R.styleable.ViewGroup_Layout_layout_height);
3380            a.recycle();
3381        }
3382
3383        /**
3384         * Creates a new set of layout parameters with the specified width
3385         * and height.
3386         *
3387         * @param width the width, either {@link #FILL_PARENT},
3388         *        {@link #WRAP_CONTENT} or a fixed size in pixels
3389         * @param height the height, either {@link #FILL_PARENT},
3390         *        {@link #WRAP_CONTENT} or a fixed size in pixels
3391         */
3392        public LayoutParams(int width, int height) {
3393            this.width = width;
3394            this.height = height;
3395        }
3396
3397        /**
3398         * Copy constructor. Clones the width and height values of the source.
3399         *
3400         * @param source The layout params to copy from.
3401         */
3402        public LayoutParams(LayoutParams source) {
3403            this.width = source.width;
3404            this.height = source.height;
3405        }
3406
3407        /**
3408         * Used internally by MarginLayoutParams.
3409         * @hide
3410         */
3411        LayoutParams() {
3412        }
3413
3414        /**
3415         * Extracts the layout parameters from the supplied attributes.
3416         *
3417         * @param a the style attributes to extract the parameters from
3418         * @param widthAttr the identifier of the width attribute
3419         * @param heightAttr the identifier of the height attribute
3420         */
3421        protected void setBaseAttributes(TypedArray a, int widthAttr, int heightAttr) {
3422            width = a.getLayoutDimension(widthAttr, "layout_width");
3423            height = a.getLayoutDimension(heightAttr, "layout_height");
3424        }
3425
3426        /**
3427         * Returns a String representation of this set of layout parameters.
3428         *
3429         * @param output the String to prepend to the internal representation
3430         * @return a String with the following format: output +
3431         *         "ViewGroup.LayoutParams={ width=WIDTH, height=HEIGHT }"
3432         *
3433         * @hide
3434         */
3435        public String debug(String output) {
3436            return output + "ViewGroup.LayoutParams={ width="
3437                    + sizeToString(width) + ", height=" + sizeToString(height) + " }";
3438        }
3439
3440        /**
3441         * Converts the specified size to a readable String.
3442         *
3443         * @param size the size to convert
3444         * @return a String instance representing the supplied size
3445         *
3446         * @hide
3447         */
3448        protected static String sizeToString(int size) {
3449            if (size == WRAP_CONTENT) {
3450                return "wrap-content";
3451            }
3452            if (size == FILL_PARENT) {
3453                return "fill-parent";
3454            }
3455            return String.valueOf(size);
3456        }
3457    }
3458
3459    /**
3460     * Per-child layout information for layouts that support margins.
3461     * See
3462     * {@link android.R.styleable#ViewGroup_MarginLayout ViewGroup Margin Layout Attributes}
3463     * for a list of all child view attributes that this class supports.
3464     */
3465    public static class MarginLayoutParams extends ViewGroup.LayoutParams {
3466        /**
3467         * The left margin in pixels of the child.
3468         */
3469        @ViewDebug.ExportedProperty
3470        public int leftMargin;
3471
3472        /**
3473         * The top margin in pixels of the child.
3474         */
3475        @ViewDebug.ExportedProperty
3476        public int topMargin;
3477
3478        /**
3479         * The right margin in pixels of the child.
3480         */
3481        @ViewDebug.ExportedProperty
3482        public int rightMargin;
3483
3484        /**
3485         * The bottom margin in pixels of the child.
3486         */
3487        @ViewDebug.ExportedProperty
3488        public int bottomMargin;
3489
3490        /**
3491         * Creates a new set of layout parameters. The values are extracted from
3492         * the supplied attributes set and context.
3493         *
3494         * @param c the application environment
3495         * @param attrs the set of attributes from which to extract the layout
3496         *              parameters' values
3497         */
3498        public MarginLayoutParams(Context c, AttributeSet attrs) {
3499            super();
3500
3501            TypedArray a = c.obtainStyledAttributes(attrs, R.styleable.ViewGroup_MarginLayout);
3502            setBaseAttributes(a,
3503                    R.styleable.ViewGroup_MarginLayout_layout_width,
3504                    R.styleable.ViewGroup_MarginLayout_layout_height);
3505
3506            int margin = a.getDimensionPixelSize(
3507                    com.android.internal.R.styleable.ViewGroup_MarginLayout_layout_margin, -1);
3508            if (margin >= 0) {
3509                leftMargin = margin;
3510                topMargin = margin;
3511                rightMargin= margin;
3512                bottomMargin = margin;
3513            } else {
3514                leftMargin = a.getDimensionPixelSize(
3515                        R.styleable.ViewGroup_MarginLayout_layout_marginLeft, 0);
3516                topMargin = a.getDimensionPixelSize(
3517                        R.styleable.ViewGroup_MarginLayout_layout_marginTop, 0);
3518                rightMargin = a.getDimensionPixelSize(
3519                        R.styleable.ViewGroup_MarginLayout_layout_marginRight, 0);
3520                bottomMargin = a.getDimensionPixelSize(
3521                        R.styleable.ViewGroup_MarginLayout_layout_marginBottom, 0);
3522            }
3523
3524            a.recycle();
3525        }
3526
3527        /**
3528         * {@inheritDoc}
3529         */
3530        public MarginLayoutParams(int width, int height) {
3531            super(width, height);
3532        }
3533
3534        /**
3535         * Copy constructor. Clones the width, height and margin values of the source.
3536         *
3537         * @param source The layout params to copy from.
3538         */
3539        public MarginLayoutParams(MarginLayoutParams source) {
3540            this.width = source.width;
3541            this.height = source.height;
3542
3543            this.leftMargin = source.leftMargin;
3544            this.topMargin = source.topMargin;
3545            this.rightMargin = source.rightMargin;
3546            this.bottomMargin = source.bottomMargin;
3547        }
3548
3549        /**
3550         * {@inheritDoc}
3551         */
3552        public MarginLayoutParams(LayoutParams source) {
3553            super(source);
3554        }
3555
3556        /**
3557         * Sets the margins, in pixels.
3558         *
3559         * @param left the left margin size
3560         * @param top the top margin size
3561         * @param right the right margin size
3562         * @param bottom the bottom margin size
3563         *
3564         * @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginLeft
3565         * @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginTop
3566         * @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginRight
3567         * @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginBottom
3568         */
3569        public void setMargins(int left, int top, int right, int bottom) {
3570            leftMargin = left;
3571            topMargin = top;
3572            rightMargin = right;
3573            bottomMargin = bottom;
3574        }
3575    }
3576}
3577