Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit edf6f4b4 authored by Chet Haase's avatar Chet Haase
Browse files

Make adding views specific to a ViewGroup's overlay

Adding views to views (possible with the new Overlay API) is weird.
This change moves the view-management facilities of Overlay to a subclass
that is specific to the overlay returned from ViewGroup.getOverlay().
So now you can add drawables to all view overlays, but only add/remove
views to/from the overlay returned from ViewGroup.getOverlay().

Also, the previous approach of using an interface for Overlay was
changed to classes for both ViewOverlay and ViewGroupOverlay.

Finally, this change makes not handling touch correctly the proper,
and documented, behavior of overlay views. There are various tricky issues
to sort out with input in overlays (including click handling as well as focus)
and we don't want developers starting to use overlays as some kind of general
container hierarchy, so we're purposely constraining overlays to have visual-only
behavior.

Issue #8459085 Overlay needs to handle touch correctly

Change-Id: I207b8dbf528f87c92369d270d8b0a6556826d207
parent a56b78dc
Loading
Loading
Loading
Loading
+12 −9
Original line number Diff line number Diff line
@@ -24966,14 +24966,6 @@ package android.view {
    field public static final int ORIENTATION_UNKNOWN = -1; // 0xffffffff
  }
  public abstract interface Overlay {
    method public abstract void add(android.graphics.drawable.Drawable);
    method public abstract void add(android.view.View);
    method public abstract void clear();
    method public abstract void remove(android.graphics.drawable.Drawable);
    method public abstract void remove(android.view.View);
  }
  public class ScaleGestureDetector {
    ctor public ScaleGestureDetector(android.content.Context, android.view.ScaleGestureDetector.OnScaleGestureListener);
    method public float getCurrentSpan();
@@ -25278,7 +25270,7 @@ package android.view {
    method public int getNextFocusUpId();
    method public android.view.View.OnFocusChangeListener getOnFocusChangeListener();
    method public int getOverScrollMode();
    method public android.view.Overlay getOverlay();
    method public android.view.ViewOverlay getOverlay();
    method public int getPaddingBottom();
    method public int getPaddingEnd();
    method public int getPaddingLeft();
@@ -26019,12 +26011,23 @@ package android.view {
    method public abstract void onChildViewRemoved(android.view.View, android.view.View);
  }
  public class ViewGroupOverlay extends android.view.ViewOverlay {
    method public void add(android.view.View);
    method public void remove(android.view.View);
  }
  public abstract interface ViewManager {
    method public abstract void addView(android.view.View, android.view.ViewGroup.LayoutParams);
    method public abstract void removeView(android.view.View);
    method public abstract void updateViewLayout(android.view.View, android.view.ViewGroup.LayoutParams);
  }
  public class ViewOverlay {
    method public void add(android.graphics.drawable.Drawable);
    method public void clear();
    method public void remove(android.graphics.drawable.Drawable);
  }
  public abstract interface ViewParent {
    method public abstract void bringChildToFront(android.view.View);
    method public abstract void childDrawableStateChanged(android.view.View);
+1 −1
Original line number Diff line number Diff line
@@ -18,7 +18,7 @@ package android.animation;
import android.graphics.Rect;

/**
 * This evaluator can be used to perform type interpolation between <code>int</code> values.
 * This evaluator can be used to perform type interpolation between <code>Rect</code> values.
 */
public class RectEvaluator implements TypeEvaluator<Rect> {

+17 −27
Original line number Diff line number Diff line
@@ -12107,7 +12107,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
        //System.out.println("Attached! " + this);
        mAttachInfo = info;
        if (mOverlay != null) {
            mOverlay.dispatchAttachedToWindow(info, visibility);
            mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility);
        }
        mWindowAttachCount++;
        // We will need to evaluate the drawable state at least once.
@@ -12178,7 +12178,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
        mAttachInfo = null;
        if (mOverlay != null) {
            mOverlay.dispatchDetachedFromWindow();
            mOverlay.getOverlayView().dispatchDetachedFromWindow();
        }
    }
@@ -12831,7 +12831,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
                    if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
                        dispatchDraw(canvas);
                        if (mOverlay != null && !mOverlay.isEmpty()) {
                            mOverlay.draw(canvas);
                            mOverlay.getOverlayView().draw(canvas);
                        }
                    } else {
                        draw(canvas);
@@ -13147,7 +13147,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
                dispatchDraw(canvas);
                if (mOverlay != null && !mOverlay.isEmpty()) {
                    mOverlay.draw(canvas);
                    mOverlay.getOverlayView().draw(canvas);
                }
            } else {
                draw(canvas);
@@ -13905,7 +13905,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
            onDrawScrollBars(canvas);
            if (mOverlay != null && !mOverlay.isEmpty()) {
                mOverlay.dispatchDraw(canvas);
                mOverlay.getOverlayView().dispatchDraw(canvas);
            }
            // we're done...
@@ -14049,34 +14049,24 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
        onDrawScrollBars(canvas);
        if (mOverlay != null && !mOverlay.isEmpty()) {
            mOverlay.dispatchDraw(canvas);
            mOverlay.getOverlayView().dispatchDraw(canvas);
        }
    }
    /**
     * Called by the addToOverlay() methods to create, attach, and size the overlay as necessary
     * Returns the overlay for this view, creating it if it does not yet exist.
     * Adding drawables to the overlay will cause them to be displayed whenever
     * the view itself is redrawn. Objects in the overlay should be actively
     * managed: remove them when they should not be displayed anymore. The
     * overlay will always have the same size as its host view.
     *
     * @return The ViewOverlay object for this view.
     * @see ViewOverlay
     */
    private void setupOverlay() {
    public ViewOverlay getOverlay() {
        if (mOverlay == null) {
            mOverlay = new ViewOverlay(mContext, this);
            mOverlay.mAttachInfo = mAttachInfo;
            mOverlay.setRight(mRight);
            mOverlay.setBottom(mBottom);
        }
        }
    /**
     * Returns the overlay for this view, creating it if it does not yet exist. Adding drawables
     * and/or views to the overlay will cause them to be displayed whenever the view itself is
     * redrawn. Objects in the overlay should be actively managed: remove them when they should
     * not be displayed anymore and invalidate this view appropriately when overlay drawables
     * change. The overlay will always have the same size as its host view.
     *
     * @return The Overlay object for this view.
     * @see Overlay
     */
    public Overlay getOverlay() {
        setupOverlay();
        return mOverlay;
    }
@@ -14360,8 +14350,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
    private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) {
        onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
        if (mOverlay != null) {
            mOverlay.setRight(mRight);
            mOverlay.setBottom(mBottom);
            mOverlay.getOverlayView().setRight(newWidth);
            mOverlay.getOverlayView().setBottom(newHeight);
        }
    }
+27 −30
Original line number Diff line number Diff line
@@ -1876,34 +1876,10 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
                    // have become out of sync.
                    removePointersFromTouchTargets(idBitsToAssign);

                    final float x = ev.getX(actionIndex);
                    final float y = ev.getY(actionIndex);

                    if (mOverlay != null) {
                        ViewOverlay overlay = (ViewOverlay) mOverlay;
                        // Check to see whether the overlay can handle the event
                        final View child = mOverlay;
                        if (canViewReceivePointerEvents(child) &&
                                isTransformedTouchPointInView(x, y, child, null)) {
                            newTouchTarget = getTouchTarget(child);
                            if (newTouchTarget != null) {
                                newTouchTarget.pointerIdBits |= idBitsToAssign;
                            } else {
                                resetCancelNextUpFlag(child);
                                if (dispatchTransformedTouchEvent(ev, false, child,
                                        idBitsToAssign)) {
                                    mLastTouchDownTime = ev.getDownTime();
                                    mLastTouchDownX = ev.getX();
                                    mLastTouchDownY = ev.getY();
                                    newTouchTarget = addTouchTarget(child, idBitsToAssign);
                                    alreadyDispatchedToNewTouchTarget = true;
                                }
                            }
                        }
                    }

                    final int childrenCount = mChildrenCount;
                    if (newTouchTarget == null && childrenCount != 0) {
                        final float x = ev.getX(actionIndex);
                        final float y = ev.getY(actionIndex);
                        // Find a child that can receive the event.
                        // Scan children from front to back.
                        final View[] children = mChildren;
@@ -2990,6 +2966,26 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
        }
    }

    /**
     * Returns the ViewGroupOverlay for this view group, creating it if it does
     * not yet exist. In addition to {@link ViewOverlay}'s support for drawables,
     * {@link ViewGroupOverlay} allows views to be added to the overlay. These
     * views, like overlay drawables, are visual-only; they do not receive input
     * events and should not be used as anything other than a temporary
     * representation of a view in a parent container, such as might be used
     * by an animation effect.
     *
     * @return The ViewGroupOverlay object for this view.
     * @see ViewGroupOverlay
     */
    @Override
    public ViewGroupOverlay getOverlay() {
        if (mOverlay == null) {
            mOverlay = new ViewGroupOverlay(mContext, this);
        }
        return (ViewGroupOverlay) mOverlay;
    }

    /**
     * Returns the index of the child to draw for this iteration. Override this
     * if you want to change the drawing order of children. By default, it
@@ -3055,11 +3051,12 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
            }
        }
        if (mOverlay != null) {
            mOverlay.mRecreateDisplayList = (mOverlay.mPrivateFlags & PFLAG_INVALIDATED)
            View overlayView = mOverlay.getOverlayView();
            overlayView.mRecreateDisplayList = (overlayView.mPrivateFlags & PFLAG_INVALIDATED)
                    == PFLAG_INVALIDATED;
            mOverlay.mPrivateFlags &= ~PFLAG_INVALIDATED;
            mOverlay.getDisplayList();
            mOverlay.mRecreateDisplayList = false;
            overlayView.mPrivateFlags &= ~PFLAG_INVALIDATED;
            overlayView.getDisplayList();
            overlayView.mRecreateDisplayList = false;
        }
    }

+27 −33
Original line number Diff line number Diff line
@@ -15,43 +15,37 @@
 */
package android.view;

import android.content.Context;
import android.graphics.drawable.Drawable;

/**
 * An overlay is an extra layer that sits on top of a View (the "host view")
 * which is drawn after all other content in that view (including children,
 * if the view is a ViewGroup). Interaction with the overlay layer is done in
 * terms of adding/removing views and drawables.
 * A group overlay is an extra layer that sits on top of a ViewGroup
 * (the "host view") which is drawn after all other content in that view
 * (including the view group's children). Interaction with the overlay
 * layer is done by adding and removing views and drawables.
 *
 * @see android.view.View#getOverlay()
 */
public interface Overlay {

    /**
     * Adds a Drawable to the overlay. The bounds of the drawable should be relative to
     * the host view. Any drawable added to the overlay should be removed when it is no longer
     * needed or no longer visible.
 * <p>ViewGroupOverlay is a subclass of {@link ViewOverlay}, adding the ability to
 * manage views for overlays on ViewGroups, in addition to the drawable
 * support in ViewOverlay.</p>
 *
     * @param drawable The Drawable to be added to the overlay. This drawable will be
     * drawn when the view redraws its overlay.
     * @see #remove(android.graphics.drawable.Drawable)
     * @see #add(View)
 * @see ViewGroup#getOverlay()
 */
    void add(Drawable drawable);
public class ViewGroupOverlay extends ViewOverlay {

    /**
     * Removes the specified Drawable from the overlay.
     *
     * @param drawable The Drawable to be removed from the overlay.
     * @see #add(android.graphics.drawable.Drawable)
     */
    void remove(Drawable drawable);
    ViewGroupOverlay(Context context, View hostView) {
        super(context, hostView);
    }

    /**
     * Adds a View to the overlay. The bounds of the added view should be
     * relative to the host view. Any view added to the overlay should be
     * removed when it is no longer needed or no longer visible.
     *
     * <p>Views in the overlay are visual-only; they do not receive input
     * events and do not participate in focus traversal. Overlay views
     * are intended to be transient, such as might be needed by a temporary
     * animation effect.</p>
     *
     * <p>If the view has a parent, the view will be removed from that parent
     * before being added to the overlay. Also, the view will be repositioned
     * such that it is in the same relative location inside the activity. For
@@ -62,20 +56,20 @@ public interface Overlay {
     * @param view The View to be added to the overlay. The added view will be
     * drawn when the overlay is drawn.
     * @see #remove(View)
     * @see #add(android.graphics.drawable.Drawable)
     * @see ViewOverlay#add(Drawable)
     */
    void add(View view);
    public void add(View view) {
        mOverlayViewGroup.add(view);
    }

    /**
     * Removes the specified View from the overlay.
     *
     * @param view The View to be removed from the overlay.
     * @see #add(View)
     * @see ViewOverlay#remove(Drawable)
     */
    void remove(View view);

    /**
     * Removes all views and drawables from the overlay.
     */
    void clear();
    public void remove(View view) {
        mOverlayViewGroup.remove(view);
    }
}
Loading