Methods Summary |
---|
public static android.view.GhostView | addGhost(View view, ViewGroup viewGroup, android.graphics.Matrix matrix)
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;
int previousRefCount = 0;
if (ghostView != null) {
View oldParent = (View) ghostView.getParent();
ViewGroup oldGrandParent = (ViewGroup) oldParent.getParent();
if (oldGrandParent != overlayViewGroup) {
previousRefCount = ghostView.mReferences;
oldGrandParent.removeView(oldParent);
ghostView = null;
}
}
if (ghostView == null) {
if (matrix == null) {
matrix = new Matrix();
calculateMatrix(view, viewGroup, matrix);
}
ghostView = new GhostView(view);
ghostView.setMatrix(matrix);
FrameLayout parent = new FrameLayout(view.getContext());
parent.setClipChildren(false);
copySize(viewGroup, parent);
copySize(viewGroup, ghostView);
parent.addView(ghostView);
ArrayList<View> tempViews = new ArrayList<View>();
int firstGhost = moveGhostViewsToTop(overlay.mOverlayViewGroup, tempViews);
insertIntoOverlay(overlay.mOverlayViewGroup, parent, ghostView, tempViews, firstGhost);
ghostView.mReferences = previousRefCount;
} else if (matrix != null) {
ghostView.setMatrix(matrix);
}
ghostView.mReferences++;
return ghostView;
|
public static android.view.GhostView | addGhost(View view, ViewGroup viewGroup)
return addGhost(view, viewGroup, null);
|
public static void | calculateMatrix(View view, ViewGroup host, android.graphics.Matrix matrix)
ViewGroup parent = (ViewGroup) view.getParent();
matrix.reset();
parent.transformMatrixToGlobal(matrix);
matrix.preTranslate(-parent.getScrollX(), -parent.getScrollY());
host.transformMatrixToLocal(matrix);
|
private static void | copySize(View from, View to)
to.setLeft(0);
to.setTop(0);
to.setRight(from.getWidth());
to.setBottom(from.getHeight());
|
public static android.view.GhostView | getGhost(View view)
return view.mGhostView;
|
private static int | getInsertIndex(ViewGroup overlayViewGroup, java.util.ArrayList viewParents, java.util.ArrayList tempParents, int firstGhost)Find the index into the overlay to insert the GhostView based on the order that the
views should be drawn. This keeps GhostViews layered in the same order
that they are ordered in the UI.
int low = firstGhost;
int high = overlayViewGroup.getChildCount() - 1;
while (low <= high) {
int mid = (low + high) / 2;
ViewGroup wrapper = (ViewGroup) overlayViewGroup.getChildAt(mid);
GhostView midView = (GhostView) wrapper.getChildAt(0);
getParents(midView.mView, tempParents);
if (isOnTop(viewParents, tempParents)) {
low = mid + 1;
} else {
high = mid - 1;
}
tempParents.clear();
}
return low;
|
private static void | getParents(View view, java.util.ArrayList parents)Adds all the parents, grandparents, etc. of view to parents.
ViewParent parent = view.getParent();
if (parent != null && parent instanceof ViewGroup) {
getParents((View) parent, parents);
}
parents.add(view);
|
private static void | insertIntoOverlay(ViewGroup viewGroup, ViewGroup wrapper, android.view.GhostView ghostView, java.util.ArrayList tempParents, int firstGhost)Inserts a GhostView into the overlay's ViewGroup in the order in which they
should be displayed by the UI.
if (firstGhost == -1) {
viewGroup.addView(wrapper);
} else {
ArrayList<View> viewParents = new ArrayList<View>();
getParents(ghostView.mView, viewParents);
int index = getInsertIndex(viewGroup, viewParents, tempParents, firstGhost);
if (index < 0 || index >= viewGroup.getChildCount()) {
viewGroup.addView(wrapper);
} else {
viewGroup.addView(wrapper, index);
}
}
|
private static boolean | isGhostWrapper(View view)Returns true if view is a GhostView's FrameLayout wrapper.
if (view instanceof FrameLayout) {
FrameLayout frameLayout = (FrameLayout) view;
if (frameLayout.getChildCount() == 1) {
View child = frameLayout.getChildAt(0);
return child instanceof GhostView;
}
}
return false;
|
private static boolean | isOnTop(java.util.ArrayList viewParents, java.util.ArrayList comparedWith)Returns true if viewParents is from a View that is on top of the comparedWith's view.
The ArrayLists contain the ancestors of views in order from top most grandparent, to
the view itself, in order. The goal is to find the first matching parent and then
compare the draw order of the siblings.
if (viewParents.isEmpty() || comparedWith.isEmpty() ||
viewParents.get(0) != comparedWith.get(0)) {
// Not the same decorView -- arbitrary ordering
return true;
}
int depth = Math.min(viewParents.size(), comparedWith.size());
for (int i = 1; i < depth; i++) {
View viewParent = viewParents.get(i);
View comparedWithParent = comparedWith.get(i);
if (viewParent != comparedWithParent) {
// i - 1 is the same parent, but these are different children.
return isOnTop(viewParent, comparedWithParent);
}
}
// one of these is the parent of the other
boolean isComparedWithTheParent = (comparedWith.size() == depth);
return isComparedWithTheParent;
|
private static boolean | isOnTop(View view, View comparedWith)Returns true if view would be drawn on top of comparedWith or false otherwise.
view and comparedWith are siblings with the same parent. This uses the logic
that dispatchDraw uses to determine which View should be drawn first.
ViewGroup parent = (ViewGroup) view.getParent();
final int childrenCount = parent.getChildCount();
final ArrayList<View> preorderedList = parent.buildOrderedChildList();
final boolean customOrder = preorderedList == null
&& parent.isChildrenDrawingOrderEnabled();
// This default value shouldn't be used because both view and comparedWith
// should be in the list. If there is an error, then just return an arbitrary
// view is on top.
boolean isOnTop = true;
for (int i = 0; i < childrenCount; i++) {
int childIndex = customOrder ? parent.getChildDrawingOrder(childrenCount, i) : i;
final View child = (preorderedList == null)
? parent.getChildAt(childIndex) : preorderedList.get(childIndex);
if (child == view) {
isOnTop = false;
break;
} else if (child == comparedWith) {
isOnTop = true;
break;
}
}
if (preorderedList != null) {
preorderedList.clear();
}
return isOnTop;
|
private static int | moveGhostViewsToTop(ViewGroup viewGroup, java.util.ArrayList tempViews)Move the GhostViews to the end so that they are on top of other views and it is easier
to do binary search for the correct location for the GhostViews in insertIntoOverlay.
final int numChildren = viewGroup.getChildCount();
if (numChildren == 0) {
return -1;
} else if (isGhostWrapper(viewGroup.getChildAt(numChildren - 1))) {
// GhostViews are already at the end
int firstGhost = numChildren - 1;
for (int i = numChildren - 2; i >= 0; i--) {
if (!isGhostWrapper(viewGroup.getChildAt(i))) {
break;
}
firstGhost = i;
}
return firstGhost;
}
// Remove all GhostViews from the middle
for (int i = numChildren - 2; i >= 0; i--) {
View child = viewGroup.getChildAt(i);
if (isGhostWrapper(child)) {
tempViews.add(child);
GhostView ghostView = (GhostView)((ViewGroup)child).getChildAt(0);
ghostView.mBeingMoved = true;
viewGroup.removeViewAt(i);
ghostView.mBeingMoved = false;
}
}
final int firstGhost;
if (tempViews.isEmpty()) {
firstGhost = -1;
} else {
firstGhost = viewGroup.getChildCount();
// Add the GhostViews to the end
for (int i = tempViews.size() - 1; i >= 0; i--) {
viewGroup.addView(tempViews.get(i));
}
tempViews.clear();
}
return firstGhost;
|
protected void | onDetachedFromWindow()
super.onDetachedFromWindow();
if (!mBeingMoved) {
setGhostedVisibility(View.VISIBLE);
mView.mGhostView = null;
final ViewGroup parent = (ViewGroup) mView.getParent();
if (parent != null) {
parent.mRecreateDisplayList = true;
parent.getDisplayList();
}
}
|
protected void | onDraw(android.graphics.Canvas canvas)
if (canvas instanceof HardwareCanvas) {
HardwareCanvas hwCanvas = (HardwareCanvas) canvas;
mView.mRecreateDisplayList = true;
RenderNode renderNode = mView.getDisplayList();
if (renderNode.isValid()) {
hwCanvas.insertReorderBarrier(); // enable shadow for this rendernode
hwCanvas.drawRenderNode(renderNode);
hwCanvas.insertInorderBarrier(); // re-disable reordering/shadows
}
}
|
public static void | removeGhost(View view)
GhostView ghostView = view.mGhostView;
if (ghostView != null) {
ghostView.mReferences--;
if (ghostView.mReferences == 0) {
ViewGroup parent = (ViewGroup) ghostView.getParent();
ViewGroup grandParent = (ViewGroup) parent.getParent();
grandParent.removeView(parent);
}
}
|
private void | setGhostedVisibility(int visibility)
mView.mViewFlags = (mView.mViewFlags & ~View.VISIBILITY_MASK) | visibility;
|
public void | setMatrix(android.graphics.Matrix matrix)
mRenderNode.setAnimationMatrix(matrix);
|
public void | setVisibility(int visibility)
super.setVisibility(visibility);
if (mView.mGhostView == this) {
int inverseVisibility = (visibility == View.VISIBLE) ? View.INVISIBLE : View.VISIBLE;
setGhostedVisibility(inverseVisibility);
}
|