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