ViewOverlayApi14.java revision 8e10080c914d1ad0784394fa3026b85535535847
1c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki/*
2c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * Copyright (C) 2016 The Android Open Source Project
3c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki *
4c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * Licensed under the Apache License, Version 2.0 (the "License");
5c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * you may not use this file except in compliance with the License.
6c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * You may obtain a copy of the License at
7c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki *
8c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki *      http://www.apache.org/licenses/LICENSE-2.0
9c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki *
10c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * Unless required by applicable law or agreed to in writing, software
11c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * distributed under the License is distributed on an "AS IS" BASIS,
12c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * See the License for the specific language governing permissions and
14c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki * limitations under the License.
15c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki */
16c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
17c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Arakipackage android.support.transition;
18c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
198e10080c914d1ad0784394fa3026b85535535847Aurimas Liutikasimport static android.support.annotation.RestrictTo.Scope.LIBRARY_GROUP;
208e10080c914d1ad0784394fa3026b85535535847Aurimas Liutikas
21c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Arakiimport android.R;
228f886fe8c7e23fe6ccb8734167c960c2ed3429c3Alan Viveretteimport android.annotation.TargetApi;
23c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Arakiimport android.content.Context;
24c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Arakiimport android.graphics.Canvas;
25c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Arakiimport android.graphics.Rect;
26c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Arakiimport android.graphics.drawable.Drawable;
278f886fe8c7e23fe6ccb8734167c960c2ed3429c3Alan Viveretteimport android.support.annotation.RequiresApi;
28c39d9c75590eca86a5e7e32a8824ba04a0d42e9bAlan Viveretteimport android.support.annotation.RestrictTo;
29a5c36708f8dd136f2a02a79709923630449be5b5Chris Banesimport android.support.v4.view.ViewCompat;
30c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Arakiimport android.view.MotionEvent;
31c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Arakiimport android.view.View;
32c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Arakiimport android.view.ViewGroup;
33c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Arakiimport android.view.ViewParent;
34c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
35c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Arakiimport java.lang.reflect.InvocationTargetException;
36c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Arakiimport java.lang.reflect.Method;
37c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Arakiimport java.util.ArrayList;
38c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
398f886fe8c7e23fe6ccb8734167c960c2ed3429c3Alan Viverette@RequiresApi(14)
408f886fe8c7e23fe6ccb8734167c960c2ed3429c3Alan Viverette@TargetApi(14)
41c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Arakiclass ViewOverlay {
42c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
43c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    /**
44c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * The actual container for the drawables (and views, if it's a ViewGroupOverlay).
45c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * All of the management and rendering details for the overlay are handled in
46c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * OverlayViewGroup.
47c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     */
48c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    protected OverlayViewGroup mOverlayViewGroup;
49c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
50c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    ViewOverlay(Context context, ViewGroup hostView, View requestingView) {
51c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        mOverlayViewGroup = new OverlayViewGroup(context, hostView, requestingView, this);
52c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    }
53c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
54c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    static ViewGroup getContentView(View view) {
55c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        View parent = view;
56c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        while (parent != null) {
57c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            if (parent.getId() == R.id.content && parent instanceof ViewGroup) {
58c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                return (ViewGroup) parent;
59c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            }
60c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            if (parent.getParent() instanceof ViewGroup) {
61c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                parent = (ViewGroup) parent.getParent();
62c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            }
63c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        }
64c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        return null;
65c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    }
66c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
67c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    public static ViewOverlay createFrom(View view) {
68c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        ViewGroup contentView = getContentView(view);
69c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        if (contentView != null) {
70c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            final int numChildren = contentView.getChildCount();
71c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            for (int i = 0; i < numChildren; ++i) {
72c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                View child = contentView.getChildAt(i);
73c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                if (child instanceof OverlayViewGroup) {
74c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                    return ((OverlayViewGroup) child).mViewOverlay;
75c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                }
76c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            }
77c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            return new ViewGroupOverlay(contentView.getContext(), contentView, view);
78c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        }
79c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        return null;
80c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    }
81c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
82c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    /**
83c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * Used internally by View and ViewGroup to handle drawing and invalidation
84c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * of the overlay
85c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     */
86c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    ViewGroup getOverlayView() {
87c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        return mOverlayViewGroup;
88c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    }
89c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
90c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    /**
91c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * Adds a Drawable to the overlay. The bounds of the drawable should be relative to
92c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * the host view. Any drawable added to the overlay should be removed when it is no longer
93c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * needed or no longer visible.
94c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     *
95c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * @param drawable The Drawable to be added to the overlay. This drawable will be
96c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     *                 drawn when the view redraws its overlay.
97c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * @see #remove(Drawable)
98c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     */
99c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    public void add(Drawable drawable) {
100c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        mOverlayViewGroup.add(drawable);
101c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    }
102c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
103c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    /**
104c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * Removes the specified Drawable from the overlay.
105c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     *
106c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * @param drawable The Drawable to be removed from the overlay.
107c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * @see #add(Drawable)
108c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     */
109c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    public void remove(Drawable drawable) {
110c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        mOverlayViewGroup.remove(drawable);
111c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    }
112c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
113c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    /**
114c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * Removes all content from the overlay.
115c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     */
116c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    public void clear() {
117c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        mOverlayViewGroup.clear();
118c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    }
119c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
120c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    boolean isEmpty() {
121c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        return mOverlayViewGroup.isEmpty();
122c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    }
123c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
124c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    /**
125c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * OverlayViewGroup is a container that View and ViewGroup use to host
126c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * drawables and views added to their overlays  ({@link ViewOverlay} and
127c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * {@link ViewGroupOverlay}, respectively). Drawables are added to the overlay
128c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * via the add/remove methods in ViewOverlay, Views are added/removed via
129c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * ViewGroupOverlay. These drawable and view objects are
130c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * drawn whenever the view itself is drawn; first the view draws its own
131c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * content (and children, if it is a ViewGroup), then it draws its overlay
132c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * (if it has one).
133c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     *
134c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * <p>Besides managing and drawing the list of drawables, this class serves
135c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * two purposes:
136c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * (1) it noops layout calls because children are absolutely positioned and
137c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * (2) it forwards all invalidation calls to its host view. The invalidation
138c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * redirect is necessary because the overlay is not a child of the host view
139c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * and invalidation cannot therefore follow the normal path up through the
140c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * parent hierarchy.</p>
141c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     *
142c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * @see View#getOverlay()
143c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * @see ViewGroup#getOverlay()
144c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     */
145c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    static class OverlayViewGroup extends ViewGroup {
146c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
147c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        static Method sInvalidateChildInParentFastMethod;
148c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
149c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        static {
150c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            try {
151c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                sInvalidateChildInParentFastMethod = ViewGroup.class.getDeclaredMethod(
152c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                        "invalidateChildInParentFast", int.class, int.class, Rect.class);
153c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            } catch (NoSuchMethodException e) {
154c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            }
155c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
156c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        }
157c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
158c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        /**
159c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki         * The View for which this is an overlay. Invalidations of the overlay are redirected to
160c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki         * this host view.
161c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki         */
162c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        ViewGroup mHostView;
163c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        View mRequestingView;
164c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        /**
165c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki         * The set of drawables to draw when the overlay is rendered.
166c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki         */
167c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        ArrayList<Drawable> mDrawables = null;
168c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        /**
169c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki         * Reference to the hosting overlay object
170c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki         */
171c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        ViewOverlay mViewOverlay;
172c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
173c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        OverlayViewGroup(Context context, ViewGroup hostView, View requestingView,
174c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                ViewOverlay viewOverlay) {
175c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            super(context);
176c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            mHostView = hostView;
177c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            mRequestingView = requestingView;
178c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            setRight(hostView.getWidth());
179c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            setBottom(hostView.getHeight());
180c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            ((ViewGroup) hostView).addView(this);
181c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            mViewOverlay = viewOverlay;
182c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        }
183c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
184c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        @Override
185c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        public boolean dispatchTouchEvent(MotionEvent ev) {
186c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            // Intercept and noop all touch events - overlays do not allow touch events
187c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            return false;
188c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        }
189c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
190c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        public void add(Drawable drawable) {
191c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            if (mDrawables == null) {
192c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
193c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                mDrawables = new ArrayList<Drawable>();
194c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            }
195c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            if (!mDrawables.contains(drawable)) {
196c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                // Make each drawable unique in the overlay; can't add it more than once
197c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                mDrawables.add(drawable);
198c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                invalidate(drawable.getBounds());
199c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                drawable.setCallback(this);
200c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            }
201c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        }
202c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
203c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        public void remove(Drawable drawable) {
204c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            if (mDrawables != null) {
205c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                mDrawables.remove(drawable);
206c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                invalidate(drawable.getBounds());
207c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                drawable.setCallback(null);
208c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            }
209c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        }
210c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
211c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        @Override
212c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        protected boolean verifyDrawable(Drawable who) {
213c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            return super.verifyDrawable(who) || (mDrawables != null && mDrawables.contains(who));
214c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        }
215c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
216c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        public void add(View child) {
217c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            if (child.getParent() instanceof ViewGroup) {
218c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                ViewGroup parent = (ViewGroup) child.getParent();
219c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                if (parent != mHostView && parent.getParent() != null) {// &&
220c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki//                        parent.isAttachedToWindow()) {
221c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                    // Moving to different container; figure out how to position child such that
222c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                    // it is in the same location on the screen
223c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                    int[] parentLocation = new int[2];
224c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                    int[] hostViewLocation = new int[2];
225c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                    parent.getLocationOnScreen(parentLocation);
226c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                    mHostView.getLocationOnScreen(hostViewLocation);
227a5c36708f8dd136f2a02a79709923630449be5b5Chris Banes                    ViewCompat.offsetLeftAndRight(child, parentLocation[0] - hostViewLocation[0]);
228a5c36708f8dd136f2a02a79709923630449be5b5Chris Banes                    ViewCompat.offsetTopAndBottom(child, parentLocation[1] - hostViewLocation[1]);
229c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                }
230c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                parent.removeView(child);
231c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki//                if (parent.getLayoutTransition() != null) {
232c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki//                    // LayoutTransition will cause the child to delay removal - cancel it
233c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki//                    parent.getLayoutTransition().cancel(LayoutTransition.DISAPPEARING);
234c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki//                }
235c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                // fail-safe if view is still attached for any reason
236c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                if (child.getParent() != null) {
237c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                    parent.removeView(child);
238c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                }
239c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            }
240c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            super.addView(child, getChildCount() - 1);
241c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        }
242c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
243c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        public void remove(View view) {
244c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            super.removeView(view);
245c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            if (isEmpty()) {
246c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                mHostView.removeView(this);
247c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            }
248c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        }
249c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
250c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        public void clear() {
251c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            removeAllViews();
252c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            if (mDrawables != null) {
253c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                mDrawables.clear();
254c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            }
255c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        }
256c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
257c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        boolean isEmpty() {
258c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            if (getChildCount() == 0 &&
259c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                    (mDrawables == null || mDrawables.size() == 0)) {
260c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                return true;
261c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            }
262c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            return false;
263c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        }
264c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
265c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        @Override
266c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        public void invalidateDrawable(Drawable drawable) {
267c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            invalidate(drawable.getBounds());
268c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        }
269c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
270c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        @Override
271c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        protected void dispatchDraw(Canvas canvas) {
272c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            int[] contentViewLocation = new int[2];
273c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            int[] hostViewLocation = new int[2];
274c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            ViewGroup parent = (ViewGroup) getParent();
275c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            mHostView.getLocationOnScreen(contentViewLocation);
276c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            mRequestingView.getLocationOnScreen(hostViewLocation);
277c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            canvas.translate(hostViewLocation[0] - contentViewLocation[0],
278c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                    hostViewLocation[1] - contentViewLocation[1]);
279c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            canvas.clipRect(
280c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                    new Rect(0, 0, mRequestingView.getWidth(), mRequestingView.getHeight()));
281c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            super.dispatchDraw(canvas);
282c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            final int numDrawables = (mDrawables == null) ? 0 : mDrawables.size();
283c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            for (int i = 0; i < numDrawables; ++i) {
284c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                mDrawables.get(i).draw(canvas);
285c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            }
286c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        }
287c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
288c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        @Override
289c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        protected void onLayout(boolean changed, int l, int t, int r, int b) {
290c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            // Noop: children are positioned absolutely
291c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        }
292c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
293c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        /*
294c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki         The following invalidation overrides exist for the purpose of redirecting invalidation to
295c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki         the host view. The overlay is not parented to the host view (since a View cannot be a
296c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki         parent), so the invalidation cannot proceed through the normal parent hierarchy.
297c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki         There is a built-in assumption that the overlay exactly covers the host view, therefore
298c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki         the invalidation rectangles received do not need to be adjusted when forwarded to
299c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki         the host view.
300c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki         */
301c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
302c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        private void getOffset(int[] offset) {
303c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            int[] contentViewLocation = new int[2];
304c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            int[] hostViewLocation = new int[2];
305c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            ViewGroup parent = (ViewGroup) getParent();
306c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            mHostView.getLocationOnScreen(contentViewLocation);
307c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            mRequestingView.getLocationOnScreen(hostViewLocation);
308c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            offset[0] = hostViewLocation[0] - contentViewLocation[0];
309c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            offset[1] = hostViewLocation[1] - contentViewLocation[1];
310c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        }
311c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
312c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        public void invalidateChildFast(View child, final Rect dirty) {
313c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            if (mHostView != null) {
314c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                // Note: This is not a "fast" invalidation. Would be nice to instead invalidate
315c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                // using DisplayList properties and a dirty rect instead of causing a real
316c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                // invalidation of the host view
317c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                int left = child.getLeft();
318c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                int top = child.getTop();
319c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                int[] offset = new int[2];
320c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                getOffset(offset);
321c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                // TODO: implement transforms
322c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki//                if (!child.getMatrix().isIdentity()) {
323c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki//                    child.transformRect(dirty);
324c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki//                }
325c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                dirty.offset(left + offset[0], top + offset[1]);
326c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                mHostView.invalidate(dirty);
327c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            }
328c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        }
329c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
330c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        /**
331c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki         * @hide
332c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki         */
3338e10080c914d1ad0784394fa3026b85535535847Aurimas Liutikas        @RestrictTo(LIBRARY_GROUP)
334c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        protected ViewParent invalidateChildInParentFast(int left, int top, Rect dirty) {
335c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            if (mHostView instanceof ViewGroup && sInvalidateChildInParentFastMethod != null) {
336c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                try {
337c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                    int[] offset = new int[2];
338c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                    getOffset(offset);
339c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                    sInvalidateChildInParentFastMethod.invoke(mHostView, left, top, dirty);
340c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                } catch (IllegalAccessException e) {
341c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                    e.printStackTrace();
342c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                } catch (InvocationTargetException e) {
343c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                    e.printStackTrace();
344c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                }
345c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            }
346c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            return null;
347c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        }
348c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
349c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        @Override
350c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        public ViewParent invalidateChildInParent(int[] location, Rect dirty) {
351c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            if (mHostView != null) {
352c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                dirty.offset(location[0], location[1]);
353c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                if (mHostView instanceof ViewGroup) {
354c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                    location[0] = 0;
355c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                    location[1] = 0;
356c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                    int[] offset = new int[2];
357c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                    getOffset(offset);
358c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                    dirty.offset(offset[0], offset[1]);
359c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                    return super.invalidateChildInParent(location, dirty);
360c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki//                    return ((ViewGroup) mHostView).invalidateChildInParent(location, dirty);
361c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                } else {
362c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                    invalidate(dirty);
363c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                }
364c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            }
365c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            return null;
366c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        }
367c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
368c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        static class TouchInterceptor extends View {
369c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            TouchInterceptor(Context context) {
370c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                super(context);
371c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            }
372c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        }
373c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    }
374c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
375c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki}
376