191cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase/* 291cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase * Copyright (C) 2013 The Android Open Source Project 391cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase * 491cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase * Licensed under the Apache License, Version 2.0 (the "License"); 591cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase * you may not use this file except in compliance with the License. 691cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase * You may obtain a copy of the License at 791cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase * 891cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase * http://www.apache.org/licenses/LICENSE-2.0 991cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase * 1091cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase * Unless required by applicable law or agreed to in writing, software 1191cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase * distributed under the License is distributed on an "AS IS" BASIS, 1291cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1391cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase * See the License for the specific language governing permissions and 1491cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase * limitations under the License. 1591cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase */ 1691cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haasepackage android.view; 1791cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase 18ce08ce539a083b31cfffd3aa98173885f0e4a3d9Chet Haaseimport android.animation.LayoutTransition; 19b4b939cf1af397cd223ac7ebb12e1d2d61e2a83eKirill Grouchnikovimport android.annotation.NonNull; 2091cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haaseimport android.content.Context; 2191cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haaseimport android.graphics.Canvas; 2291cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haaseimport android.graphics.Rect; 2391cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haaseimport android.graphics.drawable.Drawable; 2491cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase 2591cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haaseimport java.util.ArrayList; 2691cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase 2791cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase/** 28edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase * An overlay is an extra layer that sits on top of a View (the "host view") 29edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase * which is drawn after all other content in that view (including children, 30edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase * if the view is a ViewGroup). Interaction with the overlay layer is done 31edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase * by adding and removing drawables. 3291cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase * 33edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase * <p>An overlay requested from a ViewGroup is of type {@link ViewGroupOverlay}, 34edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase * which also supports adding and removing views.</p> 3591cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase * 36edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase * @see View#getOverlay() View.getOverlay() 37edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase * @see ViewGroup#getOverlay() ViewGroup.getOverlay() 38edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase * @see ViewGroupOverlay 3991cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase */ 40edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haasepublic class ViewOverlay { 4191cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase 4291cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase /** 43edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase * The actual container for the drawables (and views, if it's a ViewGroupOverlay). 44edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase * All of the management and rendering details for the overlay are handled in 45edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase * OverlayViewGroup. 4691cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase */ 47edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase OverlayViewGroup mOverlayViewGroup; 48edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase 49edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase ViewOverlay(Context context, View hostView) { 50edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase mOverlayViewGroup = new OverlayViewGroup(context, hostView); 51edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase } 5291cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase 5391cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase /** 54edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase * Used internally by View and ViewGroup to handle drawing and invalidation 55edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase * of the overlay 56edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase * @return 5791cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase */ 58edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase ViewGroup getOverlayView() { 59edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase return mOverlayViewGroup; 6091cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase } 6191cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase 62edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase /** 63b4b939cf1af397cd223ac7ebb12e1d2d61e2a83eKirill Grouchnikov * Adds a {@link Drawable} to the overlay. The bounds of the drawable should be relative to 64edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase * the host view. Any drawable added to the overlay should be removed when it is no longer 65b4b939cf1af397cd223ac7ebb12e1d2d61e2a83eKirill Grouchnikov * needed or no longer visible. Adding an already existing {@link Drawable} 66b4b939cf1af397cd223ac7ebb12e1d2d61e2a83eKirill Grouchnikov * is a no-op. Passing <code>null</code> parameter will result in an 67b4b939cf1af397cd223ac7ebb12e1d2d61e2a83eKirill Grouchnikov * {@link IllegalArgumentException} being thrown. 68edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase * 69b4b939cf1af397cd223ac7ebb12e1d2d61e2a83eKirill Grouchnikov * @param drawable The {@link Drawable} to be added to the overlay. This drawable will be 70b4b939cf1af397cd223ac7ebb12e1d2d61e2a83eKirill Grouchnikov * drawn when the view redraws its overlay. {@link Drawable}s will be drawn in the order that 71b4b939cf1af397cd223ac7ebb12e1d2d61e2a83eKirill Grouchnikov * they were added. 72edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase * @see #remove(Drawable) 73edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase */ 74b4b939cf1af397cd223ac7ebb12e1d2d61e2a83eKirill Grouchnikov public void add(@NonNull Drawable drawable) { 75edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase mOverlayViewGroup.add(drawable); 7691cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase } 7791cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase 78edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase /** 79b4b939cf1af397cd223ac7ebb12e1d2d61e2a83eKirill Grouchnikov * Removes the specified {@link Drawable} from the overlay. Removing a {@link Drawable} that was 80b4b939cf1af397cd223ac7ebb12e1d2d61e2a83eKirill Grouchnikov * not added with {@link #add(Drawable)} is a no-op. Passing <code>null</code> parameter will 81b4b939cf1af397cd223ac7ebb12e1d2d61e2a83eKirill Grouchnikov * result in an {@link IllegalArgumentException} being thrown. 82edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase * 83b4b939cf1af397cd223ac7ebb12e1d2d61e2a83eKirill Grouchnikov * @param drawable The {@link Drawable} to be removed from the overlay. 84edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase * @see #add(Drawable) 85edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase */ 86b4b939cf1af397cd223ac7ebb12e1d2d61e2a83eKirill Grouchnikov public void remove(@NonNull Drawable drawable) { 87edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase mOverlayViewGroup.remove(drawable); 8891cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase } 8991cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase 90edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase /** 91edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase * Removes all content from the overlay. 92edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase */ 93edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase public void clear() { 94edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase mOverlayViewGroup.clear(); 95633326e29f008d2b86e523cfeedcbb2a0883181fChet Haase } 96633326e29f008d2b86e523cfeedcbb2a0883181fChet Haase 97edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase boolean isEmpty() { 98edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase return mOverlayViewGroup.isEmpty(); 99edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase } 100edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase 101edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase /** 102edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase * OverlayViewGroup is a container that View and ViewGroup use to host 103edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase * drawables and views added to their overlays ({@link ViewOverlay} and 104edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase * {@link ViewGroupOverlay}, respectively). Drawables are added to the overlay 105edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase * via the add/remove methods in ViewOverlay, Views are added/removed via 106edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase * ViewGroupOverlay. These drawable and view objects are 107edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase * drawn whenever the view itself is drawn; first the view draws its own 108edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase * content (and children, if it is a ViewGroup), then it draws its overlay 109edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase * (if it has one). 110edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase * 111edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase * <p>Besides managing and drawing the list of drawables, this class serves 112edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase * two purposes: 113edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase * (1) it noops layout calls because children are absolutely positioned and 114edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase * (2) it forwards all invalidation calls to its host view. The invalidation 115edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase * redirect is necessary because the overlay is not a child of the host view 116edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase * and invalidation cannot therefore follow the normal path up through the 117edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase * parent hierarchy.</p> 118edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase * 119edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase * @see View#getOverlay() 120edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase * @see ViewGroup#getOverlay() 121edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase */ 122edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase static class OverlayViewGroup extends ViewGroup { 123edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase 124edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase /** 125edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase * The View for which this is an overlay. Invalidations of the overlay are redirected to 126edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase * this host view. 127edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase */ 128b4b939cf1af397cd223ac7ebb12e1d2d61e2a83eKirill Grouchnikov final View mHostView; 129edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase 130edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase /** 131edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase * The set of drawables to draw when the overlay is rendered. 132edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase */ 133edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase ArrayList<Drawable> mDrawables = null; 134edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase 135edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase OverlayViewGroup(Context context, View hostView) { 136edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase super(context); 137edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase mHostView = hostView; 138edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase mAttachInfo = mHostView.mAttachInfo; 1392180ba7abd7edbd5b3a880d15f828b58ab34e578Chris Craik 140edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase mRight = hostView.getWidth(); 141edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase mBottom = hostView.getHeight(); 1422180ba7abd7edbd5b3a880d15f828b58ab34e578Chris Craik // pass right+bottom directly to RenderNode, since not going through setters 1432180ba7abd7edbd5b3a880d15f828b58ab34e578Chris Craik mRenderNode.setLeftTopRightBottom(0, 0, mRight, mBottom); 144edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase } 145edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase 146b4b939cf1af397cd223ac7ebb12e1d2d61e2a83eKirill Grouchnikov public void add(@NonNull Drawable drawable) { 147b4b939cf1af397cd223ac7ebb12e1d2d61e2a83eKirill Grouchnikov if (drawable == null) { 148b4b939cf1af397cd223ac7ebb12e1d2d61e2a83eKirill Grouchnikov throw new IllegalArgumentException("drawable must be non-null"); 149b4b939cf1af397cd223ac7ebb12e1d2d61e2a83eKirill Grouchnikov } 150edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase if (mDrawables == null) { 151b4b939cf1af397cd223ac7ebb12e1d2d61e2a83eKirill Grouchnikov mDrawables = new ArrayList<>(); 152edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase } 153edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase if (!mDrawables.contains(drawable)) { 154edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase // Make each drawable unique in the overlay; can't add it more than once 155edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase mDrawables.add(drawable); 156edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase invalidate(drawable.getBounds()); 157edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase drawable.setCallback(this); 1589c17fe693deb0cc84099b619185472f192c2b52dChet Haase } 1599c17fe693deb0cc84099b619185472f192c2b52dChet Haase } 16091cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase 161b4b939cf1af397cd223ac7ebb12e1d2d61e2a83eKirill Grouchnikov public void remove(@NonNull Drawable drawable) { 162b4b939cf1af397cd223ac7ebb12e1d2d61e2a83eKirill Grouchnikov if (drawable == null) { 163b4b939cf1af397cd223ac7ebb12e1d2d61e2a83eKirill Grouchnikov throw new IllegalArgumentException("drawable must be non-null"); 164b4b939cf1af397cd223ac7ebb12e1d2d61e2a83eKirill Grouchnikov } 165edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase if (mDrawables != null) { 166edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase mDrawables.remove(drawable); 167edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase invalidate(drawable.getBounds()); 168edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase drawable.setCallback(null); 169edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase } 170edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase } 17191cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase 17239de9bfa7f922f1994c4a6dd4494c31042cf6bd3Alan Viverette @Override 173f6d87ec193f17e8dad82c9994ba7a58e975d364bAlan Viverette protected boolean verifyDrawable(@NonNull Drawable who) { 17439de9bfa7f922f1994c4a6dd4494c31042cf6bd3Alan Viverette return super.verifyDrawable(who) || (mDrawables != null && mDrawables.contains(who)); 17539de9bfa7f922f1994c4a6dd4494c31042cf6bd3Alan Viverette } 17639de9bfa7f922f1994c4a6dd4494c31042cf6bd3Alan Viverette 177b4b939cf1af397cd223ac7ebb12e1d2d61e2a83eKirill Grouchnikov public void add(@NonNull View child) { 178b4b939cf1af397cd223ac7ebb12e1d2d61e2a83eKirill Grouchnikov if (child == null) { 179b4b939cf1af397cd223ac7ebb12e1d2d61e2a83eKirill Grouchnikov throw new IllegalArgumentException("view must be non-null"); 180b4b939cf1af397cd223ac7ebb12e1d2d61e2a83eKirill Grouchnikov } 181b4b939cf1af397cd223ac7ebb12e1d2d61e2a83eKirill Grouchnikov 182edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase if (child.getParent() instanceof ViewGroup) { 183edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase ViewGroup parent = (ViewGroup) child.getParent(); 184face742d31a7a72a4bdced5594e00e51ecee6c84Chet Haase if (parent != mHostView && parent.getParent() != null && 185face742d31a7a72a4bdced5594e00e51ecee6c84Chet Haase parent.mAttachInfo != null) { 186edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase // Moving to different container; figure out how to position child such that 187edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase // it is in the same location on the screen 188edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase int[] parentLocation = new int[2]; 189edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase int[] hostViewLocation = new int[2]; 190edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase parent.getLocationOnScreen(parentLocation); 191edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase mHostView.getLocationOnScreen(hostViewLocation); 192edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase child.offsetLeftAndRight(parentLocation[0] - hostViewLocation[0]); 193edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase child.offsetTopAndBottom(parentLocation[1] - hostViewLocation[1]); 194edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase } 195edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase parent.removeView(child); 196ce08ce539a083b31cfffd3aa98173885f0e4a3d9Chet Haase if (parent.getLayoutTransition() != null) { 197ce08ce539a083b31cfffd3aa98173885f0e4a3d9Chet Haase // LayoutTransition will cause the child to delay removal - cancel it 198ce08ce539a083b31cfffd3aa98173885f0e4a3d9Chet Haase parent.getLayoutTransition().cancel(LayoutTransition.DISAPPEARING); 199ce08ce539a083b31cfffd3aa98173885f0e4a3d9Chet Haase } 200ce08ce539a083b31cfffd3aa98173885f0e4a3d9Chet Haase // fail-safe if view is still attached for any reason 201ce08ce539a083b31cfffd3aa98173885f0e4a3d9Chet Haase if (child.getParent() != null) { 202ce08ce539a083b31cfffd3aa98173885f0e4a3d9Chet Haase child.mParent = null; 203ce08ce539a083b31cfffd3aa98173885f0e4a3d9Chet Haase } 204edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase } 205edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase super.addView(child); 206edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase } 20791cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase 208b4b939cf1af397cd223ac7ebb12e1d2d61e2a83eKirill Grouchnikov public void remove(@NonNull View view) { 209b4b939cf1af397cd223ac7ebb12e1d2d61e2a83eKirill Grouchnikov if (view == null) { 210b4b939cf1af397cd223ac7ebb12e1d2d61e2a83eKirill Grouchnikov throw new IllegalArgumentException("view must be non-null"); 211b4b939cf1af397cd223ac7ebb12e1d2d61e2a83eKirill Grouchnikov } 212b4b939cf1af397cd223ac7ebb12e1d2d61e2a83eKirill Grouchnikov 213edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase super.removeView(view); 21491cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase } 21591cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase 216edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase public void clear() { 217edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase removeAllViews(); 218d8b0b233249c176b7adc1a7ee1e97f89e6a0698cChet Haase if (mDrawables != null) { 21922351c32cb23aebe0dccbe384b3a720e79e5b13aKirill Grouchnikov for (Drawable drawable : mDrawables) { 22022351c32cb23aebe0dccbe384b3a720e79e5b13aKirill Grouchnikov drawable.setCallback(null); 22122351c32cb23aebe0dccbe384b3a720e79e5b13aKirill Grouchnikov } 222d8b0b233249c176b7adc1a7ee1e97f89e6a0698cChet Haase mDrawables.clear(); 223d8b0b233249c176b7adc1a7ee1e97f89e6a0698cChet Haase } 22491cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase } 22591cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase 226edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase boolean isEmpty() { 227edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase if (getChildCount() == 0 && 228edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase (mDrawables == null || mDrawables.size() == 0)) { 229edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase return true; 230edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase } 231edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase return false; 232edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase } 23391cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase 234edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase @Override 235f6d87ec193f17e8dad82c9994ba7a58e975d364bAlan Viverette public void invalidateDrawable(@NonNull Drawable drawable) { 236edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase invalidate(drawable.getBounds()); 237edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase } 23891cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase 239edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase @Override 240edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase protected void dispatchDraw(Canvas canvas) { 241edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase super.dispatchDraw(canvas); 242edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase final int numDrawables = (mDrawables == null) ? 0 : mDrawables.size(); 243edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase for (int i = 0; i < numDrawables; ++i) { 244edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase mDrawables.get(i).draw(canvas); 245edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase } 24691cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase } 24791cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase 248edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase @Override 249edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase protected void onLayout(boolean changed, int l, int t, int r, int b) { 250edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase // Noop: children are positioned absolutely 25191cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase } 25291cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase 253edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase /* 254edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase The following invalidation overrides exist for the purpose of redirecting invalidation to 255edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase the host view. The overlay is not parented to the host view (since a View cannot be a 256edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase parent), so the invalidation cannot proceed through the normal parent hierarchy. 257edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase There is a built-in assumption that the overlay exactly covers the host view, therefore 258edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase the invalidation rectangles received do not need to be adjusted when forwarded to 259edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase the host view. 260edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase */ 261edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase 262edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase @Override 263edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase public void invalidate(Rect dirty) { 264edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase super.invalidate(dirty); 265edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase if (mHostView != null) { 266edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase mHostView.invalidate(dirty); 267edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase } 26891cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase } 26991cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase 270edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase @Override 271edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase public void invalidate(int l, int t, int r, int b) { 272edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase super.invalidate(l, t, r, b); 273edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase if (mHostView != null) { 274edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase mHostView.invalidate(l, t, r, b); 275edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase } 27691cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase } 27791cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase 278edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase @Override 279edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase public void invalidate() { 280edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase super.invalidate(); 281edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase if (mHostView != null) { 282edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase mHostView.invalidate(); 283edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase } 28491cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase } 28591cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase 286edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase @Override 287edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase void invalidate(boolean invalidateCache) { 288edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase super.invalidate(invalidateCache); 289edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase if (mHostView != null) { 290edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase mHostView.invalidate(invalidateCache); 291edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase } 29291cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase } 29391cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase 294edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase @Override 295edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) { 296edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase super.invalidateViewProperty(invalidateParent, forceRedraw); 297edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase if (mHostView != null) { 298edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase mHostView.invalidateViewProperty(invalidateParent, forceRedraw); 299edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase } 30091cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase } 30191cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase 302edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase @Override 303edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase protected void invalidateParentCaches() { 304edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase super.invalidateParentCaches(); 305edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase if (mHostView != null) { 306edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase mHostView.invalidateParentCaches(); 307edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase } 308edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase } 309edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase 310edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase @Override 311edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase protected void invalidateParentIfNeeded() { 312edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase super.invalidateParentIfNeeded(); 313edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase if (mHostView != null) { 314edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase mHostView.invalidateParentIfNeeded(); 31591cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase } 31691cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase } 31791cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase 31849e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik /** 31949e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik * @hide 32049e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik */ 32149e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik @Override 32249e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik public void damageChild(View child, final Rect dirty) { 323edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase if (mHostView != null) { 324edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase // Note: This is not a "fast" invalidation. Would be nice to instead invalidate 325edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase // using DisplayList properties and a dirty rect instead of causing a real 326edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase // invalidation of the host view 327edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase int left = child.mLeft; 328edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase int top = child.mTop; 329edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase if (!child.getMatrix().isIdentity()) { 330edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase child.transformRect(dirty); 331edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase } 332edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase dirty.offset(left, top); 333edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase mHostView.invalidate(dirty); 3349c17fe693deb0cc84099b619185472f192c2b52dChet Haase } 33591cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase } 336edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase 337e4a2d7c48e17dd1c2f59dd18e91997029a6d0bdbChet Haase /** 338e4a2d7c48e17dd1c2f59dd18e91997029a6d0bdbChet Haase * @hide 339e4a2d7c48e17dd1c2f59dd18e91997029a6d0bdbChet Haase */ 340e4a2d7c48e17dd1c2f59dd18e91997029a6d0bdbChet Haase @Override 34149e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik protected ViewParent damageChildInParent(int left, int top, Rect dirty) { 342e4a2d7c48e17dd1c2f59dd18e91997029a6d0bdbChet Haase if (mHostView instanceof ViewGroup) { 34349e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik return ((ViewGroup) mHostView).damageChildInParent(left, top, dirty); 344e4a2d7c48e17dd1c2f59dd18e91997029a6d0bdbChet Haase } 345e4a2d7c48e17dd1c2f59dd18e91997029a6d0bdbChet Haase return null; 346e4a2d7c48e17dd1c2f59dd18e91997029a6d0bdbChet Haase } 347e4a2d7c48e17dd1c2f59dd18e91997029a6d0bdbChet Haase 348edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase @Override 349edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase public ViewParent invalidateChildInParent(int[] location, Rect dirty) { 350edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase if (mHostView != null) { 351edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase dirty.offset(location[0], location[1]); 352edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase if (mHostView instanceof ViewGroup) { 353edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase location[0] = 0; 354edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase location[1] = 0; 355edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase super.invalidateChildInParent(location, dirty); 356edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase return ((ViewGroup) mHostView).invalidateChildInParent(location, dirty); 357edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase } else { 358edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase invalidate(dirty); 359edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase } 360edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase } 361edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase return null; 362edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase } 36391cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase } 364edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase 36591cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase} 366