summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
authorGeorge Mount <mount@google.com>2014-07-08 17:25:25 -0700
committerGeorge Mount <mount@google.com>2014-07-29 07:27:52 -0700
commit807e40c55cd74004ecc2392f8655fb89b3bb5304 (patch)
tree9fe9450787796e00d32e3a6837c190f663d7c4ae /core
parentea4f01070a9c8f5147eb228c413a84de78d98973 (diff)
downloadframeworks_base-807e40c55cd74004ecc2392f8655fb89b3bb5304.zip
frameworks_base-807e40c55cd74004ecc2392f8655fb89b3bb5304.tar.gz
frameworks_base-807e40c55cd74004ecc2392f8655fb89b3bb5304.tar.bz2
Allow a "ghost view" that paint a different view from the overlay.
Bug 15744995 The ghost view doesn't route touch events, but hides another view in its normal parent, and paints it as a child of another ViewGroup or ViewGroupOverlay. Change-Id: I352e14c366ccfb7303cee1dbff8563c673fd12ff
Diffstat (limited to 'core')
-rw-r--r--core/java/android/view/GhostView.java125
-rw-r--r--core/java/android/view/View.java18
2 files changed, 140 insertions, 3 deletions
diff --git a/core/java/android/view/GhostView.java b/core/java/android/view/GhostView.java
new file mode 100644
index 0000000..1aa8d99
--- /dev/null
+++ b/core/java/android/view/GhostView.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.view;
+
+import android.graphics.Canvas;
+import android.graphics.Matrix;
+
+/**
+ * This view draws another View in an Overlay without changing the parent. It will not be drawn
+ * by its parent because its visibility is set to INVISIBLE, but will be drawn
+ * here using its render node. When the GhostView is set to INVISIBLE, the View it is
+ * shadowing will become VISIBLE and when the GhostView becomes VISIBLE, the shadowed
+ * view becomes INVISIBLE.
+ * @hide
+ */
+public class GhostView extends View {
+ private final Matrix mMatrix = new Matrix();
+ private final View mView;
+
+ private GhostView(View view, ViewGroup host) {
+ super(view.getContext());
+ mView = view;
+ setMatrix(host);
+ mView.mGhostView = this;
+ final ViewGroup parent = (ViewGroup) mView.getParent();
+ setLeft(0);
+ setTop(0);
+ setRight(host.getWidth());
+ setBottom(host.getHeight());
+ setGhostedVisibility(View.INVISIBLE);
+ parent.mRecreateDisplayList = true;
+ parent.getDisplayList();
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ if (canvas instanceof HardwareCanvas) {
+ HardwareCanvas hwCanvas = (HardwareCanvas) canvas;
+ int saveCount = hwCanvas.save(Canvas.MATRIX_SAVE_FLAG);
+ canvas.concat(mMatrix);
+ mView.mRecreateDisplayList = true;
+ RenderNode renderNode = mView.getDisplayList();
+ if (renderNode.isValid()) {
+ hwCanvas.drawRenderNode(renderNode);
+ }
+ hwCanvas.restoreToCount(saveCount);
+ }
+ }
+
+ @Override
+ public void setVisibility(@Visibility int visibility) {
+ super.setVisibility(visibility);
+ if (mView.mGhostView == this) {
+ int inverseVisibility = (visibility == View.VISIBLE) ? View.INVISIBLE : View.VISIBLE;
+ setGhostedVisibility(inverseVisibility);
+ }
+ }
+
+ private void setGhostedVisibility(int visibility) {
+ mView.mViewFlags = (mView.mViewFlags & ~View.VISIBILITY_MASK) | visibility;
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+ setGhostedVisibility(View.VISIBLE);
+ mView.mGhostView = null;
+ final ViewGroup parent = (ViewGroup) mView.getParent();
+ parent.mRecreateDisplayList = true;
+ parent.getDisplayList();
+ }
+
+ private void setMatrix(ViewGroup host) {
+ host.transformMatrixToLocal(mMatrix);
+ ViewGroup parent = (ViewGroup) mView.getParent();
+ parent.transformMatrixToGlobal(mMatrix);
+ mMatrix.postTranslate(-parent.getScrollX(), -parent.getScrollY());
+ }
+
+ public static GhostView addGhost(View view, ViewGroup viewGroup) {
+ if (!(view.getParent() instanceof ViewGroup)) {
+ throw new IllegalArgumentException("Ghosted views must be parented by a ViewGroup");
+ }
+ ViewGroupOverlay overlay = viewGroup.getOverlay();
+ ViewOverlay.OverlayViewGroup overlayViewGroup = overlay.mOverlayViewGroup;
+ GhostView ghostView = view.mGhostView;
+ if (ghostView != null) {
+ ViewGroup oldParent = (ViewGroup) ghostView.getParent();
+ if (oldParent != overlayViewGroup) {
+ oldParent.removeView(ghostView);
+ ghostView = null;
+ }
+ }
+ if (ghostView == null) {
+ ghostView = new GhostView(view, (ViewGroup) overlayViewGroup.mHostView);
+ overlay.add(ghostView);
+ }
+ return ghostView;
+ }
+
+ public static void removeGhost(View view) {
+ GhostView ghostView = view.mGhostView;
+ if (ghostView != null) {
+ ViewGroup parent = (ViewGroup) ghostView.getParent();
+ parent.removeView(ghostView);
+ }
+ }
+
+ public static GhostView getGhost(View view) {
+ return view.mGhostView;
+ }
+}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 4c1c2f9..81b5c20 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -17,9 +17,7 @@
package android.view;
import android.animation.AnimatorInflater;
-import android.animation.RevealAnimator;
import android.animation.StateListAnimator;
-import android.animation.ValueAnimator;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -3520,6 +3518,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
private int[] mTempNestedScrollConsumed;
/**
+ * An overlay is going to draw this View instead of being drawn as part of this
+ * View's parent. mGhostView is the View in the Overlay that must be invalidated
+ * when this view is invalidated.
+ */
+ GhostView mGhostView;
+
+ /**
* Simple constructor to use when creating a view from code.
*
* @param context The Context the view is running in, through which it can
@@ -10284,6 +10289,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
*
* @hide
*/
+ @ViewDebug.ExportedProperty(category = "drawing")
public float getTransitionAlpha() {
return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1;
}
@@ -11371,6 +11377,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,
boolean fullInvalidate) {
+ if (mGhostView != null) {
+ mGhostView.invalidate(invalidateCache);
+ return;
+ }
+
if (skipInvalidate()) {
return;
}
@@ -11408,7 +11419,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
}
- // Damage the entire IsolatedZVolume recieving this view's shadow.
+ // Damage the entire IsolatedZVolume receiving this view's shadow.
if (isHardwareAccelerated() && getZ() != 0) {
damageShadowReceiver();
}
@@ -19397,6 +19408,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @return The name used of the View to be used to identify Views in Transitions or null
* if no name has been given.
*/
+ @ViewDebug.ExportedProperty
public String getTransitionName() {
return mTransitionName;
}