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