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

Commit abe6de47 authored by Pat Manning's avatar Pat Manning Committed by Android (Google) Code Review
Browse files

Merge "Refactor ArrowTipView so it can be customized and used in any drag layer." into udc-qpr-dev

parents a8aefb6e 58b6145f
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -518,4 +518,8 @@
        <!-- The icon drawable of a widget category. -->
        <attr name="sectionDrawable" format="reference" />
    </declare-styleable>

    <declare-styleable name="ArrowTipView">
        <attr name="arrowTipBackground" format="color" />
    </declare-styleable>
</resources>
+3 −0
Original line number Diff line number Diff line
@@ -378,4 +378,7 @@
        <item name="horizontalPadding">16dp</item>
    </style>

    <style name="ArrowTipStyle">
        <item name="arrowTipBackground">@color/arrow_tip_view_bg</item>
    </style>
</resources>
+79 −43
Original line number Diff line number Diff line
@@ -16,8 +16,13 @@

package com.android.launcher3.views;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.TypedArray;
import android.graphics.CornerPathEffect;
import android.graphics.Paint;
import android.graphics.Rect;
@@ -33,18 +38,16 @@ import android.widget.TextView;

import androidx.annotation.Nullable;
import androidx.annotation.Px;
import androidx.core.content.ContextCompat;

import com.android.app.animation.Interpolators;
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
import com.android.launcher3.dragndrop.DragLayer;
import com.android.launcher3.graphics.TriangleShape;

/**
 * A base class for arrow tip view in launcher
 * A base class for arrow tip view in launcher.
 */
public class ArrowTipView extends AbstractFloatingView {

@@ -54,33 +57,46 @@ public class ArrowTipView extends AbstractFloatingView {
    private static final long SHOW_DURATION_MS = 300;
    private static final long HIDE_DURATION_MS = 100;

    protected final BaseDraggingActivity mActivity;
    private final ActivityContext mActivityContext;
    private final Handler mHandler = new Handler();
    private final int mArrowWidth;
    private final int mArrowMinOffset;
    private boolean mIsPointingUp;
    private Runnable mOnClosed;
    private View mArrowView;
    private final int mArrowWidth;
    private final int mArrowMinOffset;
    private final int mArrowViewPaintColor;

    private AnimatorSet mOpenAnimator = new AnimatorSet();
    private AnimatorSet mCloseAnimator = new AnimatorSet();

    public ArrowTipView(Context context) {
        this(context, false);
    }

    public ArrowTipView(Context context, boolean isPointingUp) {
        this(context, isPointingUp, R.layout.arrow_toast);
    }

    public ArrowTipView(Context context, boolean isPointingUp, int layoutId) {
        super(context, null, 0);
        mActivity = BaseDraggingActivity.fromContext(context);
        mActivityContext = ActivityContext.lookupContext(context);
        mIsPointingUp = isPointingUp;
        mArrowWidth = context.getResources().getDimensionPixelSize(R.dimen.arrow_toast_arrow_width);
        mArrowWidth = context.getResources().getDimensionPixelSize(
                R.dimen.arrow_toast_arrow_width);
        mArrowMinOffset = context.getResources().getDimensionPixelSize(
                R.dimen.dynamic_grid_cell_border_spacing);
        init(context);
        TypedArray ta = context.obtainStyledAttributes(R.styleable.ArrowTipView);
        mArrowViewPaintColor = ta.getColor(R.styleable.ArrowTipView_arrowTipBackground,
                context.getColor(R.color.arrow_tip_view_bg));
        ta.recycle();
        init(context, layoutId);
    }

    @Override
    public boolean onControllerInterceptTouchEvent(MotionEvent ev) {
        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
            close(true);
            if (mActivity.getDragLayer().isEventOverView(this, ev)) {
            if (mActivityContext.getDragLayer().isEventOverView(this, ev)) {
                return true;
            }
        }
@@ -89,18 +105,15 @@ public class ArrowTipView extends AbstractFloatingView {

    @Override
    protected void handleClose(boolean animate) {
        if (mOpenAnimator.isStarted()) {
            mOpenAnimator.cancel();
        }
        if (mIsOpen) {
            if (animate) {
                animate().alpha(0f)
                        .withLayer()
                        .setStartDelay(0)
                        .setDuration(HIDE_DURATION_MS)
                        .setInterpolator(Interpolators.ACCELERATE)
                        .withEndAction(() -> mActivity.getDragLayer().removeView(this))
                        .start();
                mCloseAnimator.start();
            } else {
                animate().cancel();
                mActivity.getDragLayer().removeView(this);
                mCloseAnimator.cancel();
                mActivityContext.getDragLayer().removeView(this);
            }
            if (mOnClosed != null) mOnClosed.run();
            mIsOpen = false;
@@ -112,12 +125,31 @@ public class ArrowTipView extends AbstractFloatingView {
        return (type & TYPE_ON_BOARD_POPUP) != 0;
    }

    private void init(Context context) {
        inflate(context, R.layout.arrow_toast, this);
    private void init(Context context, int layoutId) {
        inflate(context, layoutId, this);
        setOrientation(LinearLayout.VERTICAL);

        mArrowView = findViewById(R.id.arrow);
        updateArrowTipInView();
        setAlpha(0);

        // Create default open animator.
        mOpenAnimator.play(ObjectAnimator.ofFloat(this, ALPHA, 1f));
        mOpenAnimator.setStartDelay(SHOW_DELAY_MS);
        mOpenAnimator.setDuration(SHOW_DURATION_MS);
        mOpenAnimator.setInterpolator(Interpolators.DECELERATE);

        // Create default close animator.
        mCloseAnimator.play(ObjectAnimator.ofFloat(this, ALPHA, 0));
        mCloseAnimator.setStartDelay(0);
        mCloseAnimator.setDuration(HIDE_DURATION_MS);
        mCloseAnimator.setInterpolator(Interpolators.ACCELERATE);
        mCloseAnimator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                mActivityContext.getDragLayer().removeView(ArrowTipView.this);
            }
        });
    }

    /**
@@ -153,10 +185,10 @@ public class ArrowTipView extends AbstractFloatingView {
    public ArrowTipView show(
            String text, int gravity, int arrowMarginStart, int top, boolean shouldAutoClose) {
        ((TextView) findViewById(R.id.text)).setText(text);
        ViewGroup parent = mActivity.getDragLayer();
        ViewGroup parent = mActivityContext.getDragLayer();
        parent.addView(this);

        DeviceProfile grid = mActivity.getDeviceProfile();
        DeviceProfile grid = mActivityContext.getDeviceProfile();

        DragLayer.LayoutParams params = (DragLayer.LayoutParams) getLayoutParams();
        params.gravity = gravity;
@@ -185,14 +217,8 @@ public class ArrowTipView extends AbstractFloatingView {
        if (shouldAutoClose) {
            mHandler.postDelayed(() -> handleClose(true), AUTO_CLOSE_TIMEOUT_MILLIS);
        }
        setAlpha(0);
        animate()
                .alpha(1f)
                .withLayer()
                .setStartDelay(SHOW_DELAY_MS)
                .setDuration(SHOW_DURATION_MS)
                .setInterpolator(Interpolators.DECELERATE)
                .start();

        mOpenAnimator.start();
        return this;
    }

@@ -273,7 +299,7 @@ public class ArrowTipView extends AbstractFloatingView {
     */
    @Nullable private ArrowTipView showAtLocation(String text, @Px int arrowXCoord,
            @Px int yCoordDownPointingTip, @Px int yCoordUpPointingTip, boolean shouldAutoClose) {
        ViewGroup parent = mActivity.getDragLayer();
        ViewGroup parent = mActivityContext.getDragLayer();
        @Px int parentViewWidth = parent.getWidth();
        @Px int parentViewHeight = parent.getHeight();
        @Px int maxTextViewWidth = getContext().getResources()
@@ -288,8 +314,10 @@ public class ArrowTipView extends AbstractFloatingView {
        TextView textView = findViewById(R.id.text);
        textView.setText(text);
        textView.setMaxWidth(maxTextViewWidth);
        if (parent.indexOfChild(this) < 0) {
            parent.addView(this);
            requestLayout();
        }

        post(() -> {
            // Adjust the tooltip horizontally.
@@ -333,14 +361,8 @@ public class ArrowTipView extends AbstractFloatingView {
        if (shouldAutoClose) {
            mHandler.postDelayed(() -> handleClose(true), AUTO_CLOSE_TIMEOUT_MILLIS);
        }
        setAlpha(0);
        animate()
                .alpha(1f)
                .withLayer()
                .setStartDelay(SHOW_DELAY_MS)
                .setDuration(SHOW_DURATION_MS)
                .setInterpolator(Interpolators.DECELERATE)
                .start();

        mOpenAnimator.start();
        return this;
    }

@@ -351,7 +373,7 @@ public class ArrowTipView extends AbstractFloatingView {
        Paint arrowPaint = arrowDrawable.getPaint();
        @Px int arrowTipRadius = getContext().getResources()
                .getDimensionPixelSize(R.dimen.arrow_toast_corner_radius);
        arrowPaint.setColor(ContextCompat.getColor(getContext(), R.color.arrow_tip_view_bg));
        arrowPaint.setColor(mArrowViewPaintColor);
        arrowPaint.setPathEffect(new CornerPathEffect(arrowTipRadius));
        mArrowView.setBackground(arrowDrawable);
        // Add negative margin so that the rounded corners on base of arrow are not visible.
@@ -378,4 +400,18 @@ public class ArrowTipView extends AbstractFloatingView {
        super.onConfigurationChanged(newConfig);
        close(/* animate= */ false);
    }

    /**
     * Sets a custom animation to run on open of the ArrowTipView.
     */
    public void setCustomOpenAnimation(AnimatorSet animator) {
        mOpenAnimator = animator;
    }

    /**
     * Sets a custom animation to run on close of the ArrowTipView.
     */
    public void setCustomCloseAnimation(AnimatorSet animator) {
        mCloseAnimator = animator;
    }
}