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.content.Context;
22c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Arakiimport android.graphics.Canvas;
23c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Arakiimport android.graphics.Rect;
24c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Arakiimport android.graphics.drawable.Drawable;
254e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Arakiimport android.support.annotation.NonNull;
268f886fe8c7e23fe6ccb8734167c960c2ed3429c3Alan Viveretteimport android.support.annotation.RequiresApi;
27c39d9c75590eca86a5e7e32a8824ba04a0d42e9bAlan Viveretteimport android.support.annotation.RestrictTo;
28a5c36708f8dd136f2a02a79709923630449be5b5Chris Banesimport android.support.v4.view.ViewCompat;
29c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Arakiimport android.view.MotionEvent;
30c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Arakiimport android.view.View;
31c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Arakiimport android.view.ViewGroup;
32c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Arakiimport android.view.ViewParent;
33c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
34c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Arakiimport java.lang.reflect.InvocationTargetException;
35c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Arakiimport java.lang.reflect.Method;
36c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Arakiimport java.util.ArrayList;
37c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
388f886fe8c7e23fe6ccb8734167c960c2ed3429c3Alan Viverette@RequiresApi(14)
394e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Arakiclass ViewOverlayApi14 implements ViewOverlayImpl {
40c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
41c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    /**
42c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * The actual container for the drawables (and views, if it's a ViewGroupOverlay).
43c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * All of the management and rendering details for the overlay are handled in
44c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * OverlayViewGroup.
45c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     */
46c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    protected OverlayViewGroup mOverlayViewGroup;
47c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
484e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    ViewOverlayApi14(Context context, ViewGroup hostView, View requestingView) {
49c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        mOverlayViewGroup = new OverlayViewGroup(context, hostView, requestingView, this);
50c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    }
51c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
52c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    static ViewGroup getContentView(View view) {
53c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        View parent = view;
54c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        while (parent != null) {
554e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            if (parent.getId() == android.R.id.content && parent instanceof ViewGroup) {
56c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                return (ViewGroup) parent;
57c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            }
58c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            if (parent.getParent() instanceof ViewGroup) {
59c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                parent = (ViewGroup) parent.getParent();
60c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            }
61c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        }
62c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        return null;
63c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    }
64c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
654e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    static ViewOverlayApi14 createFrom(View view) {
66c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        ViewGroup contentView = getContentView(view);
67c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        if (contentView != null) {
68c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            final int numChildren = contentView.getChildCount();
69c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            for (int i = 0; i < numChildren; ++i) {
70c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                View child = contentView.getChildAt(i);
71c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                if (child instanceof OverlayViewGroup) {
72c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                    return ((OverlayViewGroup) child).mViewOverlay;
73c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                }
74c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            }
754e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            return new ViewGroupOverlayApi14(contentView.getContext(), contentView, view);
76c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        }
77c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        return null;
78c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    }
79c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
80c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    /**
81c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * Used internally by View and ViewGroup to handle drawing and invalidation
82c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * of the overlay
83c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     */
84c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    ViewGroup getOverlayView() {
85c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        return mOverlayViewGroup;
86c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    }
87c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
884e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    @Override
894e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    public void add(@NonNull Drawable drawable) {
90c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        mOverlayViewGroup.add(drawable);
91c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    }
92c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
934e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    @Override
94c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    public void clear() {
95c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        mOverlayViewGroup.clear();
96c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    }
97c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
984e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    @Override
994e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    public void remove(@NonNull Drawable drawable) {
1004e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        mOverlayViewGroup.remove(drawable);
1014e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki    }
1024e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki
103c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    boolean isEmpty() {
104c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        return mOverlayViewGroup.isEmpty();
105c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    }
106c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
1074e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki
108c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    /**
109c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * OverlayViewGroup is a container that View and ViewGroup use to host
11050ce74b0963de66b294761c045428562d946b65aYuichi Araki     * drawables and views added to their overlays  ({@code ViewOverlay} and
11150ce74b0963de66b294761c045428562d946b65aYuichi Araki     * {@code ViewGroupOverlay}, respectively). Drawables are added to the overlay
112c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * via the add/remove methods in ViewOverlay, Views are added/removed via
113c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * ViewGroupOverlay. These drawable and view objects are
114c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * drawn whenever the view itself is drawn; first the view draws its own
115c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * content (and children, if it is a ViewGroup), then it draws its overlay
116c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * (if it has one).
117c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     *
118c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * <p>Besides managing and drawing the list of drawables, this class serves
119c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * two purposes:
120c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * (1) it noops layout calls because children are absolutely positioned and
121c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * (2) it forwards all invalidation calls to its host view. The invalidation
122c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * redirect is necessary because the overlay is not a child of the host view
123c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * and invalidation cannot therefore follow the normal path up through the
124c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * parent hierarchy.</p>
125c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     *
126c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * @see View#getOverlay()
127c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     * @see ViewGroup#getOverlay()
128c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki     */
129c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    static class OverlayViewGroup extends ViewGroup {
130c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
131c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        static Method sInvalidateChildInParentFastMethod;
132c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
133c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        static {
134c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            try {
135c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                sInvalidateChildInParentFastMethod = ViewGroup.class.getDeclaredMethod(
136c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                        "invalidateChildInParentFast", int.class, int.class, Rect.class);
137c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            } catch (NoSuchMethodException e) {
138c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            }
139c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
140c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        }
141c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
142c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        /**
143c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki         * The View for which this is an overlay. Invalidations of the overlay are redirected to
144c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki         * this host view.
145c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki         */
146c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        ViewGroup mHostView;
147c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        View mRequestingView;
148c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        /**
149c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki         * The set of drawables to draw when the overlay is rendered.
150c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki         */
151c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        ArrayList<Drawable> mDrawables = null;
152c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        /**
153c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki         * Reference to the hosting overlay object
154c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki         */
1554e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki        ViewOverlayApi14 mViewOverlay;
156c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
157c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        OverlayViewGroup(Context context, ViewGroup hostView, View requestingView,
1584e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                ViewOverlayApi14 viewOverlay) {
159c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            super(context);
160c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            mHostView = hostView;
161c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            mRequestingView = requestingView;
162c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            setRight(hostView.getWidth());
163c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            setBottom(hostView.getHeight());
1644e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            hostView.addView(this);
165c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            mViewOverlay = viewOverlay;
166c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        }
167c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
168c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        @Override
169c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        public boolean dispatchTouchEvent(MotionEvent ev) {
170c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            // Intercept and noop all touch events - overlays do not allow touch events
171c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            return false;
172c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        }
173c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
174c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        public void add(Drawable drawable) {
175c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            if (mDrawables == null) {
176c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
1774e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                mDrawables = new ArrayList<>();
178c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            }
179c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            if (!mDrawables.contains(drawable)) {
180c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                // Make each drawable unique in the overlay; can't add it more than once
181c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                mDrawables.add(drawable);
182c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                invalidate(drawable.getBounds());
183c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                drawable.setCallback(this);
184c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            }
185c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        }
186c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
187c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        public void remove(Drawable drawable) {
188c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            if (mDrawables != null) {
189c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                mDrawables.remove(drawable);
190c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                invalidate(drawable.getBounds());
191c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                drawable.setCallback(null);
192c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            }
193c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        }
194c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
195c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        @Override
196ce318dbf0020462e651049fd4f32dc226b656f5bAurimas Liutikas        protected boolean verifyDrawable(@NonNull Drawable who) {
197c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            return super.verifyDrawable(who) || (mDrawables != null && mDrawables.contains(who));
198c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        }
199c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
200c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        public void add(View child) {
201c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            if (child.getParent() instanceof ViewGroup) {
202c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                ViewGroup parent = (ViewGroup) child.getParent();
2034e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                if (parent != mHostView && parent.getParent() != null
2044e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                        && ViewCompat.isAttachedToWindow(parent)) {
205c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                    // Moving to different container; figure out how to position child such that
206c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                    // it is in the same location on the screen
207c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                    int[] parentLocation = new int[2];
208c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                    int[] hostViewLocation = new int[2];
209c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                    parent.getLocationOnScreen(parentLocation);
210c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                    mHostView.getLocationOnScreen(hostViewLocation);
211a5c36708f8dd136f2a02a79709923630449be5b5Chris Banes                    ViewCompat.offsetLeftAndRight(child, parentLocation[0] - hostViewLocation[0]);
212a5c36708f8dd136f2a02a79709923630449be5b5Chris Banes                    ViewCompat.offsetTopAndBottom(child, parentLocation[1] - hostViewLocation[1]);
213c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                }
214c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                parent.removeView(child);
215c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki//                if (parent.getLayoutTransition() != null) {
216c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki//                    // LayoutTransition will cause the child to delay removal - cancel it
217c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki//                    parent.getLayoutTransition().cancel(LayoutTransition.DISAPPEARING);
218c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki//                }
219c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                // fail-safe if view is still attached for any reason
220c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                if (child.getParent() != null) {
221c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                    parent.removeView(child);
222c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                }
223c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            }
224c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            super.addView(child, getChildCount() - 1);
225c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        }
226c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
227c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        public void remove(View view) {
228c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            super.removeView(view);
229c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            if (isEmpty()) {
230c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                mHostView.removeView(this);
231c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            }
232c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        }
233c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
234c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        public void clear() {
235c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            removeAllViews();
236c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            if (mDrawables != null) {
237c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                mDrawables.clear();
238c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            }
239c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        }
240c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
241c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        boolean isEmpty() {
2424e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki            return getChildCount() == 0
2434e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki                    && (mDrawables == null || mDrawables.size() == 0);
244c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        }
245c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
246c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        @Override
247ce318dbf0020462e651049fd4f32dc226b656f5bAurimas Liutikas        public void invalidateDrawable(@NonNull Drawable drawable) {
248c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            invalidate(drawable.getBounds());
249c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        }
250c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
251c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        @Override
252c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        protected void dispatchDraw(Canvas canvas) {
253c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            int[] contentViewLocation = new int[2];
254c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            int[] hostViewLocation = new int[2];
255c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            mHostView.getLocationOnScreen(contentViewLocation);
256c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            mRequestingView.getLocationOnScreen(hostViewLocation);
257c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            canvas.translate(hostViewLocation[0] - contentViewLocation[0],
258c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                    hostViewLocation[1] - contentViewLocation[1]);
259c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            canvas.clipRect(
260c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                    new Rect(0, 0, mRequestingView.getWidth(), mRequestingView.getHeight()));
261c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            super.dispatchDraw(canvas);
262c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            final int numDrawables = (mDrawables == null) ? 0 : mDrawables.size();
263c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            for (int i = 0; i < numDrawables; ++i) {
264c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                mDrawables.get(i).draw(canvas);
265c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            }
266c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        }
267c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
268c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        @Override
269c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        protected void onLayout(boolean changed, int l, int t, int r, int b) {
270c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            // Noop: children are positioned absolutely
271c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        }
272c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
273c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        /*
274c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki         The following invalidation overrides exist for the purpose of redirecting invalidation to
275c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki         the host view. The overlay is not parented to the host view (since a View cannot be a
276c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki         parent), so the invalidation cannot proceed through the normal parent hierarchy.
277c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki         There is a built-in assumption that the overlay exactly covers the host view, therefore
278c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki         the invalidation rectangles received do not need to be adjusted when forwarded to
279c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki         the host view.
280c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki         */
281c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
282c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        private void getOffset(int[] offset) {
283c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            int[] contentViewLocation = new int[2];
284c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            int[] hostViewLocation = new int[2];
285c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            mHostView.getLocationOnScreen(contentViewLocation);
286c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            mRequestingView.getLocationOnScreen(hostViewLocation);
287c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            offset[0] = hostViewLocation[0] - contentViewLocation[0];
288c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            offset[1] = hostViewLocation[1] - contentViewLocation[1];
289c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        }
290c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
291c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        public void invalidateChildFast(View child, final Rect dirty) {
292c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            if (mHostView != null) {
293c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                // Note: This is not a "fast" invalidation. Would be nice to instead invalidate
294c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                // using DisplayList properties and a dirty rect instead of causing a real
295c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                // invalidation of the host view
296c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                int left = child.getLeft();
297c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                int top = child.getTop();
298c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                int[] offset = new int[2];
299c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                getOffset(offset);
300c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                // TODO: implement transforms
301c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki//                if (!child.getMatrix().isIdentity()) {
302c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki//                    child.transformRect(dirty);
303c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki//                }
304c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                dirty.offset(left + offset[0], top + offset[1]);
305c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                mHostView.invalidate(dirty);
306c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            }
307c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        }
308c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
309c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        /**
310c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki         * @hide
311c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki         */
3128e10080c914d1ad0784394fa3026b85535535847Aurimas Liutikas        @RestrictTo(LIBRARY_GROUP)
313c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        protected ViewParent invalidateChildInParentFast(int left, int top, Rect dirty) {
314c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            if (mHostView instanceof ViewGroup && sInvalidateChildInParentFastMethod != null) {
315c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                try {
316c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                    int[] offset = new int[2];
317c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                    getOffset(offset);
318c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                    sInvalidateChildInParentFastMethod.invoke(mHostView, left, top, dirty);
319c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                } catch (IllegalAccessException e) {
320c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                    e.printStackTrace();
321c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                } catch (InvocationTargetException e) {
322c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                    e.printStackTrace();
323c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                }
324c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            }
325c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            return null;
326c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        }
327c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
328ce318dbf0020462e651049fd4f32dc226b656f5bAurimas Liutikas        @SuppressWarnings("deprecation")
329c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        @Override
330c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        public ViewParent invalidateChildInParent(int[] location, Rect dirty) {
331c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            if (mHostView != null) {
332c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                dirty.offset(location[0], location[1]);
333c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                if (mHostView instanceof ViewGroup) {
334c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                    location[0] = 0;
335c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                    location[1] = 0;
336c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                    int[] offset = new int[2];
337c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                    getOffset(offset);
338c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                    dirty.offset(offset[0], offset[1]);
339c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                    return super.invalidateChildInParent(location, dirty);
340c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki//                    return ((ViewGroup) mHostView).invalidateChildInParent(location, dirty);
341c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                } else {
342c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                    invalidate(dirty);
343c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                }
344c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            }
345c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            return null;
346c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        }
347c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
348c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        static class TouchInterceptor extends View {
349c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            TouchInterceptor(Context context) {
350c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki                super(context);
351c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki            }
352c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki        }
353c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki    }
354c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki
3554e5a72756eb66c31baf1a3054c66520f1c3f5b8cYuichi Araki
356c876cd8f9334e2423de00836009f3fd7a9566938Yuichi Araki}
357