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