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

Commit 0ce63252 authored by Ats Jenk's avatar Ats Jenk Committed by Android (Google) Code Review
Browse files

Merge "Animation for bubbles home gesture" into tm-qpr-dev

parents e9ed7210 d8aa1c31
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -52,6 +52,19 @@ public class Interpolators {
     */
    public static final Interpolator LINEAR_OUT_SLOW_IN = new PathInterpolator(0f, 0f, 0.2f, 1f);

    /**
     * The accelerated emphasized interpolator. Used for hero / emphasized movement of content that
     * is disappearing e.g. when moving off screen.
     */
    public static final Interpolator EMPHASIZED_ACCELERATE = new PathInterpolator(
            0.3f, 0f, 0.8f, 0.15f);

    /**
     * The decelerating emphasized interpolator. Used for hero / emphasized movement of content that
     * is appearing e.g. when coming from off screen
     */
    public static final Interpolator EMPHASIZED_DECELERATE = new PathInterpolator(
            0.05f, 0.7f, 0.1f, 1f);
    /**
     * Interpolator to be used when animating a move based on a click. Pair with enough duration.
     */
+1 −1
Original line number Diff line number Diff line
@@ -1512,7 +1512,7 @@ public class BubbleController {
        public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) {
            mBubblePositioner.setImeVisible(imeVisible, imeHeight);
            if (mStackView != null) {
                mStackView.animateForIme(imeVisible);
                mStackView.setImeVisible(imeVisible);
            }
        }
    }
+3 −0
Original line number Diff line number Diff line
@@ -46,6 +46,9 @@ public class BubbleDebugConfig {
    static final boolean DEBUG_OVERFLOW = false;
    static final boolean DEBUG_USER_EDUCATION = false;
    static final boolean DEBUG_POSITIONER = false;
    public static final boolean DEBUG_COLLAPSE_ANIMATOR = false;
    static final boolean DEBUG_BUBBLE_GESTURE = false;
    public static boolean DEBUG_EXPANDED_VIEW_DRAGGING = false;

    private static final boolean FORCE_SHOW_USER_EDUCATION = false;
    private static final String FORCE_SHOW_USER_EDUCATION_SETTING =
+248 −28
Original line number Diff line number Diff line
@@ -43,10 +43,13 @@ import android.graphics.CornerPathEffect;
import android.graphics.Outline;
import android.graphics.Paint;
import android.graphics.Picture;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.drawable.ShapeDrawable;
import android.os.RemoteException;
import android.util.AttributeSet;
import android.util.FloatProperty;
import android.util.IntProperty;
import android.util.Log;
import android.util.TypedValue;
import android.view.LayoutInflater;
@@ -75,6 +78,48 @@ import java.io.PrintWriter;
public class BubbleExpandedView extends LinearLayout {
    private static final String TAG = TAG_WITH_CLASS_NAME ? "BubbleExpandedView" : TAG_BUBBLES;

    /** {@link IntProperty} for updating bottom clip */
    public static final IntProperty<BubbleExpandedView> BOTTOM_CLIP_PROPERTY =
            new IntProperty<BubbleExpandedView>("bottomClip") {
                @Override
                public void setValue(BubbleExpandedView expandedView, int value) {
                    expandedView.setBottomClip(value);
                }

                @Override
                public Integer get(BubbleExpandedView expandedView) {
                    return expandedView.mBottomClip;
                }
            };

    /** {@link FloatProperty} for updating taskView or overflow alpha */
    public static final FloatProperty<BubbleExpandedView> CONTENT_ALPHA =
            new FloatProperty<BubbleExpandedView>("contentAlpha") {
                @Override
                public void setValue(BubbleExpandedView expandedView, float value) {
                    expandedView.setContentAlpha(value);
                }

                @Override
                public Float get(BubbleExpandedView expandedView) {
                    return expandedView.getContentAlpha();
                }
            };

    /** {@link FloatProperty} for updating manage button alpha */
    public static final FloatProperty<BubbleExpandedView> MANAGE_BUTTON_ALPHA =
            new FloatProperty<BubbleExpandedView>("manageButtonAlpha") {
                @Override
                public void setValue(BubbleExpandedView expandedView, float value) {
                    expandedView.mManageButton.setAlpha(value);
                }

                @Override
                public Float get(BubbleExpandedView expandedView) {
                    return expandedView.mManageButton.getAlpha();
                }
            };

    // The triangle pointing to the expanded view
    private View mPointerView;
    @Nullable private int[] mExpandedViewContainerLocation;
@@ -90,7 +135,7 @@ public class BubbleExpandedView extends LinearLayout {

    /**
     * Whether we want the {@code TaskView}'s content to be visible (alpha = 1f). If
     * {@link #mIsAlphaAnimating} is true, this may not reflect the {@code TaskView}'s actual alpha
     * {@link #mIsAnimating} is true, this may not reflect the {@code TaskView}'s actual alpha
     * value until the animation ends.
     */
    private boolean mIsContentVisible = false;
@@ -99,12 +144,13 @@ public class BubbleExpandedView extends LinearLayout {
     * Whether we're animating the {@code TaskView}'s alpha value. If so, we will hold off on
     * applying alpha changes from {@link #setContentVisibility} until the animation ends.
     */
    private boolean mIsAlphaAnimating = false;
    private boolean mIsAnimating = false;

    private int mPointerWidth;
    private int mPointerHeight;
    private float mPointerRadius;
    private float mPointerOverlap;
    private final PointF mPointerPos = new PointF();
    private CornerPathEffect mPointerEffect;
    private ShapeDrawable mCurrentPointer;
    private ShapeDrawable mTopPointer;
@@ -113,11 +159,13 @@ public class BubbleExpandedView extends LinearLayout {
    private float mCornerRadius = 0f;
    private int mBackgroundColorFloating;
    private boolean mUsingMaxHeight;

    private int mTopClip = 0;
    private int mBottomClip = 0;
    @Nullable private Bubble mBubble;
    private PendingIntent mPendingIntent;
    // TODO(b/170891664): Don't use a flag, set the BubbleOverflow object instead
    private boolean mIsOverflow;
    private boolean mIsClipping;

    private BubbleController mController;
    private BubbleStackView mStackView;
@@ -268,7 +316,8 @@ public class BubbleExpandedView extends LinearLayout {
        mExpandedViewContainer.setOutlineProvider(new ViewOutlineProvider() {
            @Override
            public void getOutline(View view, Outline outline) {
                outline.setRoundRect(0, 0, view.getWidth(), view.getHeight(), mCornerRadius);
                Rect clip = new Rect(0, mTopClip, view.getWidth(), view.getHeight() - mBottomClip);
                outline.setRoundRect(clip, mCornerRadius);
            }
        });
        mExpandedViewContainer.setClipToOutline(true);
@@ -429,7 +478,7 @@ public class BubbleExpandedView extends LinearLayout {
     * ordering surfaces during animations. When content is drawn on top of the app (e.g. bubble
     * being dragged out, the manage menu) this is set to false, otherwise it should be true.
     */
    void setSurfaceZOrderedOnTop(boolean onTop) {
    public void setSurfaceZOrderedOnTop(boolean onTop) {
        if (mTaskView == null) {
            return;
        }
@@ -510,12 +559,12 @@ public class BubbleExpandedView extends LinearLayout {
    }

    /**
     * Whether we are currently animating the {@code TaskView}'s alpha value. If this is set to
     * Whether we are currently animating the {@code TaskView}. If this is set to
     * true, calls to {@link #setContentVisibility} will not be applied until this is set to false
     * again.
     */
    void setAlphaAnimating(boolean animating) {
        mIsAlphaAnimating = animating;
    public void setAnimating(boolean animating) {
        mIsAnimating = animating;

        // If we're done animating, apply the correct
        if (!animating) {
@@ -524,15 +573,128 @@ public class BubbleExpandedView extends LinearLayout {
    }

    /**
     * Sets the alpha of the underlying {@code TaskView}, since changing the expanded view's alpha
     * does not affect the {@code TaskView} since it uses a Surface.
     * Get alpha from underlying {@code TaskView} if this view is for a bubble.
     * Or get alpha for the overflow view if this view is for overflow.
     *
     * @return alpha for the content being shown
     */
    void setTaskViewAlpha(float alpha) {
    public float getContentAlpha() {
        if (mIsOverflow) {
            return mOverflowView.getAlpha();
        }
        if (mTaskView != null) {
            return mTaskView.getAlpha();
        }
        return 1f;
    }

    /**
     * Set alpha of the underlying {@code TaskView} if this view is for a bubble.
     * Or set alpha for the overflow view if this view is for overflow.
     *
     * Changing expanded view's alpha does not affect the {@code TaskView} since it uses a Surface.
     */
    public void setContentAlpha(float alpha) {
        if (mIsOverflow) {
            mOverflowView.setAlpha(alpha);
        } else if (mTaskView != null) {
            mTaskView.setAlpha(alpha);
        }
        mPointerView.setAlpha(alpha);
        setAlpha(alpha);
    }

    /**
     * Set translation Y for the expanded view content.
     * Excludes manage button and pointer.
     */
    public void setContentTranslationY(float translationY) {
        mExpandedViewContainer.setTranslationY(translationY);

        // Left or right pointer can become detached when moving the view up
        if (translationY <= 0 && (isShowingLeftPointer() || isShowingRightPointer())) {
            // Y coordinate where the pointer would start to get detached from the expanded view.
            // Takes into account bottom clipping and rounded corners
            float detachPoint =
                    mExpandedViewContainer.getBottom() - mBottomClip - mCornerRadius + translationY;
            float pointerBottom = mPointerPos.y + mPointerHeight;
            // If pointer bottom is past detach point, move it in by that many pixels
            float horizontalShift = 0;
            if (pointerBottom > detachPoint) {
                horizontalShift = pointerBottom - detachPoint;
            }
            if (isShowingLeftPointer()) {
                // Move left pointer right
                movePointerBy(horizontalShift, 0);
            } else {
                // Move right pointer left
                movePointerBy(-horizontalShift, 0);
            }
            // Hide pointer if it is moved by entire width
            mPointerView.setVisibility(
                    horizontalShift > mPointerWidth ? View.INVISIBLE : View.VISIBLE);
        }
    }

    /**
     * Update alpha value for the manage button
     */
    public void setManageButtonAlpha(float alpha) {
        mManageButton.setAlpha(alpha);
    }

    /**
     * Set {@link #setTranslationY(float) translationY} for the manage button
     */
    public void setManageButtonTranslationY(float translationY) {
        mManageButton.setTranslationY(translationY);
    }

    /**
     * Set top clipping for the view
     */
    public void setTopClip(int clip) {
        mTopClip = clip;
        onContainerClipUpdate();
    }

    /**
     * Set bottom clipping for the view
     */
    public void setBottomClip(int clip) {
        mBottomClip = clip;
        onContainerClipUpdate();
    }

    private void onContainerClipUpdate() {
        if (mTopClip == 0 && mBottomClip == 0) {
            if (mIsClipping) {
                mIsClipping = false;
                if (mTaskView != null) {
                    mTaskView.setClipBounds(null);
                    mTaskView.setEnableSurfaceClipping(false);
                }
                mExpandedViewContainer.invalidateOutline();
            }
        } else {
            if (!mIsClipping) {
                mIsClipping = true;
                if (mTaskView != null) {
                    mTaskView.setEnableSurfaceClipping(true);
                }
            }
            mExpandedViewContainer.invalidateOutline();
            if (mTaskView != null) {
                mTaskView.setClipBounds(new Rect(0, mTopClip, mTaskView.getWidth(),
                        mTaskView.getHeight() - mBottomClip));
            }
        }
    }

    /**
     * Move pointer from base position
     */
    public void movePointerBy(float x, float y) {
        mPointerView.setTranslationX(mPointerPos.x + x);
        mPointerView.setTranslationY(mPointerPos.y + y);
    }

    /**
@@ -543,13 +705,13 @@ public class BubbleExpandedView extends LinearLayout {
     * Note that this contents visibility doesn't affect visibility at {@link android.view.View},
     * and setting {@code false} actually means rendering the contents in transparent.
     */
    void setContentVisibility(boolean visibility) {
    public void setContentVisibility(boolean visibility) {
        if (DEBUG_BUBBLE_EXPANDED_VIEW) {
            Log.d(TAG, "setContentVisibility: visibility=" + visibility
                    + " bubble=" + getBubbleKey());
        }
        mIsContentVisible = visibility;
        if (mTaskView != null && !mIsAlphaAnimating) {
        if (mTaskView != null && !mIsAnimating) {
            mTaskView.setAlpha(visibility ? 1f : 0f);
            mPointerView.setAlpha(visibility ? 1f : 0f);
        }
@@ -560,6 +722,44 @@ public class BubbleExpandedView extends LinearLayout {
        return mTaskView;
    }

    @VisibleForTesting
    public BubbleOverflowContainerView getOverflow() {
        return mOverflowView;
    }


    /**
     * Return content height: taskView or overflow.
     * Takes into account clippings set by {@link #setTopClip(int)} and {@link #setBottomClip(int)}
     *
     * @return if bubble is for overflow, return overflow height, otherwise return taskView height
     */
    public int getContentHeight() {
        if (mIsOverflow) {
            return mOverflowView.getHeight() - mTopClip - mBottomClip;
        }
        if (mTaskView != null) {
            return mTaskView.getHeight() - mTopClip - mBottomClip;
        }
        return 0;
    }

    /**
     * Return bottom position of the content on screen
     *
     * @return if bubble is for overflow, return value for overflow, otherwise taskView
     */
    public int getContentBottomOnScreen() {
        Rect out = new Rect();
        if (mIsOverflow) {
            mOverflowView.getBoundsOnScreen(out);
        }
        if (mTaskView != null) {
            mTaskView.getBoundsOnScreen(out);
        }
        return out.bottom;
    }

    int getTaskId() {
        return mTaskId;
    }
@@ -728,27 +928,47 @@ public class BubbleExpandedView extends LinearLayout {
        post(() -> {
            mCurrentPointer = showVertically ? onLeft ? mLeftPointer : mRightPointer : mTopPointer;
            updatePointerView();
            float pointerY;
            float pointerX;
            if (showVertically) {
                pointerY = bubbleCenter - (mPointerWidth / 2f);
                pointerX = onLeft
                mPointerPos.y = bubbleCenter - (mPointerWidth / 2f);
                mPointerPos.x = onLeft
                        ? -mPointerHeight + mPointerOverlap
                        : getWidth() - mPaddingRight - mPointerOverlap;
            } else {
                pointerY = mPointerOverlap;
                pointerX = bubbleCenter - (mPointerWidth / 2f);
                mPointerPos.y = mPointerOverlap;
                mPointerPos.x = bubbleCenter - (mPointerWidth / 2f);
            }
            if (animate) {
                mPointerView.animate().translationX(pointerX).translationY(pointerY).start();
                mPointerView.animate().translationX(mPointerPos.x).translationY(
                        mPointerPos.y).start();
            } else {
                mPointerView.setTranslationY(pointerY);
                mPointerView.setTranslationX(pointerX);
                mPointerView.setTranslationY(mPointerPos.y);
                mPointerView.setTranslationX(mPointerPos.x);
                mPointerView.setVisibility(VISIBLE);
            }
        });
    }

    /**
     * Return true if pointer is shown on the left
     */
    public boolean isShowingLeftPointer() {
        return mCurrentPointer == mLeftPointer;
    }

    /**
     * Return true if pointer is shown on the right
     */
    public boolean isShowingRightPointer() {
        return mCurrentPointer == mRightPointer;
    }

    /**
     * Return width of the current pointer
     */
    public int getPointerWidth() {
        return mPointerWidth;
    }

    /**
     * Position of the manage button displayed in the expanded view. Used for placing user
     * education about the manage button.
+25 −0
Original line number Diff line number Diff line
@@ -344,6 +344,14 @@ public class BubblePositioner {
        return mImeVisible ? mImeHeight : 0;
    }

    /** Return top position of the IME if it's visible */
    public int getImeTop() {
        if (mImeVisible) {
            return getScreenRect().bottom - getImeHeight() - getInsets().bottom;
        }
        return 0;
    }

    /** Sets whether the IME is visible. **/
    public void setImeVisible(boolean visible, int height) {
        mImeVisible = visible;
@@ -706,4 +714,21 @@ public class BubblePositioner {
    public void setPinnedLocation(PointF point) {
        mPinLocation = point;
    }

    /**
     * Navigation bar has an area where system gestures can be started from.
     *
     * @return {@link Rect} for system navigation bar gesture zone
     */
    public Rect getNavBarGestureZone() {
        // Gesture zone height from the bottom
        int gestureZoneHeight = mContext.getResources().getDimensionPixelSize(
                com.android.internal.R.dimen.navigation_bar_gesture_height);
        Rect screen = getScreenRect();
        return new Rect(
                screen.left,
                screen.bottom - gestureZoneHeight,
                screen.right,
                screen.bottom);
    }
}
Loading