ViewOverlay.java revision b4b939cf1af397cd223ac7ebb12e1d2d61e2a83e
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
17339de9bfa7f922f1994c4a6dd4494c31042cf6bd3Alan Viverette        protected boolean verifyDrawable(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) {
219d8b0b233249c176b7adc1a7ee1e97f89e6a0698cChet Haase                mDrawables.clear();
220d8b0b233249c176b7adc1a7ee1e97f89e6a0698cChet Haase            }
22191cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase        }
22291cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase
223edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase        boolean isEmpty() {
224edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase            if (getChildCount() == 0 &&
225edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase                    (mDrawables == null || mDrawables.size() == 0)) {
226edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase                return true;
227edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase            }
228edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase            return false;
229edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase        }
23091cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase
231edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase        @Override
232edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase        public void invalidateDrawable(Drawable drawable) {
233edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase            invalidate(drawable.getBounds());
234edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase        }
23591cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase
236edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase        @Override
237edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase        protected void dispatchDraw(Canvas canvas) {
238edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase            super.dispatchDraw(canvas);
239edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase            final int numDrawables = (mDrawables == null) ? 0 : mDrawables.size();
240edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase            for (int i = 0; i < numDrawables; ++i) {
241edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase                mDrawables.get(i).draw(canvas);
242edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase            }
24391cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase        }
24491cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase
245edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase        @Override
246edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase        protected void onLayout(boolean changed, int l, int t, int r, int b) {
247edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase            // Noop: children are positioned absolutely
24891cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase        }
24991cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase
250edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase        /*
251edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase         The following invalidation overrides exist for the purpose of redirecting invalidation to
252edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase         the host view. The overlay is not parented to the host view (since a View cannot be a
253edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase         parent), so the invalidation cannot proceed through the normal parent hierarchy.
254edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase         There is a built-in assumption that the overlay exactly covers the host view, therefore
255edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase         the invalidation rectangles received do not need to be adjusted when forwarded to
256edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase         the host view.
257edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase         */
258edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase
259edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase        @Override
260edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase        public void invalidate(Rect dirty) {
261edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase            super.invalidate(dirty);
262edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase            if (mHostView != null) {
263edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase                mHostView.invalidate(dirty);
264edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase            }
26591cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase        }
26691cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase
267edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase        @Override
268edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase        public void invalidate(int l, int t, int r, int b) {
269edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase            super.invalidate(l, t, r, b);
270edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase            if (mHostView != null) {
271edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase                mHostView.invalidate(l, t, r, b);
272edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase            }
27391cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase        }
27491cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase
275edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase        @Override
276edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase        public void invalidate() {
277edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase            super.invalidate();
278edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase            if (mHostView != null) {
279edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase                mHostView.invalidate();
280edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase            }
28191cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase        }
28291cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase
283edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase        @Override
284edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase        void invalidate(boolean invalidateCache) {
285edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase            super.invalidate(invalidateCache);
286edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase            if (mHostView != null) {
287edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase                mHostView.invalidate(invalidateCache);
288edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase            }
28991cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase        }
29091cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase
291edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase        @Override
292edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase        void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
293edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase            super.invalidateViewProperty(invalidateParent, forceRedraw);
294edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase            if (mHostView != null) {
295edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase                mHostView.invalidateViewProperty(invalidateParent, forceRedraw);
296edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase            }
29791cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase        }
29891cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase
299edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase        @Override
300edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase        protected void invalidateParentCaches() {
301edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase            super.invalidateParentCaches();
302edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase            if (mHostView != null) {
303edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase                mHostView.invalidateParentCaches();
304edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase            }
305edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase        }
306edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase
307edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase        @Override
308edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase        protected void invalidateParentIfNeeded() {
309edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase            super.invalidateParentIfNeeded();
310edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase            if (mHostView != null) {
311edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase                mHostView.invalidateParentIfNeeded();
31291cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase            }
31391cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase        }
31491cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase
31549e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik        /**
31649e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik         * @hide
31749e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik         */
31849e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik        @Override
31949e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik        public void damageChild(View child, final Rect dirty) {
320edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase            if (mHostView != null) {
321edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase                // Note: This is not a "fast" invalidation. Would be nice to instead invalidate
322edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase                // using DisplayList properties and a dirty rect instead of causing a real
323edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase                // invalidation of the host view
324edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase                int left = child.mLeft;
325edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase                int top = child.mTop;
326edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase                if (!child.getMatrix().isIdentity()) {
327edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase                    child.transformRect(dirty);
328edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase                }
329edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase                dirty.offset(left, top);
330edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase                mHostView.invalidate(dirty);
3319c17fe693deb0cc84099b619185472f192c2b52dChet Haase            }
33291cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase        }
333edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase
334e4a2d7c48e17dd1c2f59dd18e91997029a6d0bdbChet Haase        /**
335e4a2d7c48e17dd1c2f59dd18e91997029a6d0bdbChet Haase         * @hide
336e4a2d7c48e17dd1c2f59dd18e91997029a6d0bdbChet Haase         */
337e4a2d7c48e17dd1c2f59dd18e91997029a6d0bdbChet Haase        @Override
33849e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik        protected ViewParent damageChildInParent(int left, int top, Rect dirty) {
339e4a2d7c48e17dd1c2f59dd18e91997029a6d0bdbChet Haase            if (mHostView instanceof ViewGroup) {
34049e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik                return ((ViewGroup) mHostView).damageChildInParent(left, top, dirty);
341e4a2d7c48e17dd1c2f59dd18e91997029a6d0bdbChet Haase            }
342e4a2d7c48e17dd1c2f59dd18e91997029a6d0bdbChet Haase            return null;
343e4a2d7c48e17dd1c2f59dd18e91997029a6d0bdbChet Haase        }
344e4a2d7c48e17dd1c2f59dd18e91997029a6d0bdbChet Haase
345edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase        @Override
346edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase        public ViewParent invalidateChildInParent(int[] location, Rect dirty) {
347edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase            if (mHostView != null) {
348edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase                dirty.offset(location[0], location[1]);
349edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase                if (mHostView instanceof ViewGroup) {
350edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase                    location[0] = 0;
351edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase                    location[1] = 0;
352edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase                    super.invalidateChildInParent(location, dirty);
353edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase                    return ((ViewGroup) mHostView).invalidateChildInParent(location, dirty);
354edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase                } else {
355edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase                    invalidate(dirty);
356edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase                }
357edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase            }
358edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase            return null;
359edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase        }
36091cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase    }
361edf6f4b49f6e77c349f5055372ce381b74f12efbChet Haase
36291cedf1c3dbf7a52c2892294b2e5ba3e40ef3583Chet Haase}
363