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