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) { 24136d9a6dfba1a3c39aa3224fdef15cb79e2e9b9a0Chris Craik /* 24236d9a6dfba1a3c39aa3224fdef15cb79e2e9b9a0Chris Craik * The OverlayViewGroup doesn't draw with a DisplayList, because 24336d9a6dfba1a3c39aa3224fdef15cb79e2e9b9a0Chris Craik * draw(Canvas, View, long) is never called on it. This is fine, since it doesn't need 24436d9a6dfba1a3c39aa3224fdef15cb79e2e9b9a0Chris Craik * RenderNode/DisplayList features, and can just draw into the owner's Canvas. 24536d9a6dfba1a3c39aa3224fdef15cb79e2e9b9a0Chris Craik * 24636d9a6dfba1a3c39aa3224fdef15cb79e2e9b9a0Chris Craik * This means that we need to insert reorder barriers manually though, so that children 24736d9a6dfba1a3c39aa3224fdef15cb79e2e9b9a0Chris Craik * of the OverlayViewGroup can cast shadows and Z reorder with each other. 24836d9a6dfba1a3c39aa3224fdef15cb79e2e9b9a0Chris Craik */ 24936d9a6dfba1a3c39aa3224fdef15cb79e2e9b9a0Chris Craik canvas.insertReorderBarrier(); 25036d9a6dfba1a3c39aa3224fdef15cb79e2e9b9a0Chris Craik 251edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase super.dispatchDraw(canvas); 25236d9a6dfba1a3c39aa3224fdef15cb79e2e9b9a0Chris Craik 25336d9a6dfba1a3c39aa3224fdef15cb79e2e9b9a0Chris Craik canvas.insertInorderBarrier(); 254edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase final int numDrawables = (mDrawables == null) ? 0 : mDrawables.size(); 255edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase for (int i = 0; i < numDrawables; ++i) { 256edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase mDrawables.get(i).draw(canvas); 257edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase } 25891cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase } 25991cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase 260edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase @Override 261edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase protected void onLayout(boolean changed, int l, int t, int r, int b) { 262edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase // Noop: children are positioned absolutely 26391cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase } 26491cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase 265edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase /* 266edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase The following invalidation overrides exist for the purpose of redirecting invalidation to 267edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase the host view. The overlay is not parented to the host view (since a View cannot be a 268edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase parent), so the invalidation cannot proceed through the normal parent hierarchy. 269edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase There is a built-in assumption that the overlay exactly covers the host view, therefore 270edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase the invalidation rectangles received do not need to be adjusted when forwarded to 271edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase the host view. 272edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase */ 273edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase 274edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase @Override 275edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase public void invalidate(Rect dirty) { 276edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase super.invalidate(dirty); 277edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase if (mHostView != null) { 278edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase mHostView.invalidate(dirty); 279edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase } 28091cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase } 28191cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase 282edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase @Override 283edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase public void invalidate(int l, int t, int r, int b) { 284edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase super.invalidate(l, t, r, b); 285edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase if (mHostView != null) { 286edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase mHostView.invalidate(l, t, r, b); 287edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase } 28891cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase } 28991cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase 290edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase @Override 291edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase public void invalidate() { 292edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase super.invalidate(); 293edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase if (mHostView != null) { 294edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase mHostView.invalidate(); 295edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase } 29691cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase } 29791cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase 2983f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik /** @hide */ 299edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase @Override 3003f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik public void invalidate(boolean invalidateCache) { 301edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase super.invalidate(invalidateCache); 302edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase if (mHostView != null) { 303edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase mHostView.invalidate(invalidateCache); 304edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase } 30591cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase } 30691cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase 307edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase @Override 308edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) { 309edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase super.invalidateViewProperty(invalidateParent, forceRedraw); 310edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase if (mHostView != null) { 311edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase mHostView.invalidateViewProperty(invalidateParent, forceRedraw); 312edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase } 31391cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase } 31491cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase 315edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase @Override 316edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase protected void invalidateParentCaches() { 317edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase super.invalidateParentCaches(); 318edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase if (mHostView != null) { 319edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase mHostView.invalidateParentCaches(); 320edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase } 321edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase } 322edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase 323edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase @Override 324edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase protected void invalidateParentIfNeeded() { 325edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase super.invalidateParentIfNeeded(); 326edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase if (mHostView != null) { 327edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase mHostView.invalidateParentIfNeeded(); 32891cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase } 32991cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase } 33091cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase 33149e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik @Override 3329de95db4f28f88c37b1443d20b308ce02407fd74Chris Craik public void onDescendantInvalidated(@NonNull View child, @NonNull View target) { 333bc44b1a693c2a06087abf50d151f015783f1c533Chris Craik if (mHostView != null) { 334bc44b1a693c2a06087abf50d151f015783f1c533Chris Craik if (mHostView instanceof ViewGroup) { 335bc44b1a693c2a06087abf50d151f015783f1c533Chris Craik // Propagate invalidate through the host... 336bc44b1a693c2a06087abf50d151f015783f1c533Chris Craik ((ViewGroup) mHostView).onDescendantInvalidated(mHostView, target); 337edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase 338bc44b1a693c2a06087abf50d151f015783f1c533Chris Craik // ...and also this view, since it will hold the descendant, and must later 339bc44b1a693c2a06087abf50d151f015783f1c533Chris Craik // propagate the calls to update display lists if dirty 340bc44b1a693c2a06087abf50d151f015783f1c533Chris Craik super.onDescendantInvalidated(child, target); 341bc44b1a693c2a06087abf50d151f015783f1c533Chris Craik } else { 342bc44b1a693c2a06087abf50d151f015783f1c533Chris Craik // Can't use onDescendantInvalidated because host isn't a ViewGroup - fall back 343bc44b1a693c2a06087abf50d151f015783f1c533Chris Craik // to invalidating. 344bc44b1a693c2a06087abf50d151f015783f1c533Chris Craik invalidate(); 345bc44b1a693c2a06087abf50d151f015783f1c533Chris Craik } 346e4a2d7c48e17dd1c2f59dd18e91997029a6d0bdbChet Haase } 347e4a2d7c48e17dd1c2f59dd18e91997029a6d0bdbChet Haase } 348e4a2d7c48e17dd1c2f59dd18e91997029a6d0bdbChet Haase 349edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase @Override 350edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase public ViewParent invalidateChildInParent(int[] location, Rect dirty) { 351edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase if (mHostView != null) { 352edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase dirty.offset(location[0], location[1]); 353edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase if (mHostView instanceof ViewGroup) { 354edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase location[0] = 0; 355edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase location[1] = 0; 356edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase super.invalidateChildInParent(location, dirty); 357edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase return ((ViewGroup) mHostView).invalidateChildInParent(location, dirty); 358edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase } else { 359edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase invalidate(dirty); 360edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase } 361edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase } 362edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase return null; 363edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase } 36491cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase } 365edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase 36691cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase} 367