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

Commit 6ef6c160 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Ripple and opa diamond animation plays after a timeout (1/2)" into pi-dev

parents 631f55ba 3aa0ddef
Loading
Loading
Loading
Loading
+55 −2
Original line number Diff line number Diff line
@@ -26,9 +26,12 @@ import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.SystemProperties;
import android.view.DisplayListCanvas;
import android.view.RenderNodeAnimator;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.animation.Interpolator;

import com.android.systemui.Interpolators;
@@ -56,14 +59,17 @@ public class KeyButtonRipple extends Drawable {
    private float mGlowAlpha = 0f;
    private float mGlowScale = 1f;
    private boolean mPressed;
    private boolean mVisible;
    private boolean mDrawingHardwareGlow;
    private int mMaxWidth;
    private boolean mLastDark;
    private boolean mDark;
    private boolean mDelayTouchFeedback;

    private final Interpolator mInterpolator = new LogInterpolator();
    private boolean mSupportHardware;
    private final View mTargetView;
    private final Handler mHandler = new Handler();

    private final HashSet<Animator> mRunningAnimations = new HashSet<>();
    private final ArrayList<Animator> mTmpArray = new ArrayList<>();
@@ -77,6 +83,10 @@ public class KeyButtonRipple extends Drawable {
        mDark = darkIntensity >= 0.5f;
    }

    public void setDelayTouchFeedback(boolean delay) {
        mDelayTouchFeedback = delay;
    }

    private Paint getRipplePaint() {
        if (mRipplePaint == null) {
            mRipplePaint = new Paint();
@@ -211,7 +221,16 @@ public class KeyButtonRipple extends Drawable {
        }
    }

    /**
     * Abort the ripple while it is delayed and before shown used only when setShouldDelayStartTouch
     * is enabled.
     */
    public void abortDelayedRipple() {
        mHandler.removeCallbacksAndMessages(null);
    }

    private void cancelAnimations() {
        mVisible = false;
        mTmpArray.addAll(mRunningAnimations);
        int size = mTmpArray.size();
        for (int i = 0; i < size; i++) {
@@ -220,11 +239,21 @@ public class KeyButtonRipple extends Drawable {
        }
        mTmpArray.clear();
        mRunningAnimations.clear();
        mHandler.removeCallbacksAndMessages(null);
    }

    private void setPressedSoftware(boolean pressed) {
        if (pressed) {
            if (mDelayTouchFeedback) {
                if (mRunningAnimations.isEmpty()) {
                    mHandler.removeCallbacksAndMessages(null);
                    mHandler.postDelayed(this::enterSoftware, ViewConfiguration.getTapTimeout());
                } else if (mVisible) {
                    enterSoftware();
                }
            } else {
                enterSoftware();
            }
        } else {
            exitSoftware();
        }
@@ -232,6 +261,7 @@ public class KeyButtonRipple extends Drawable {

    private void enterSoftware() {
        cancelAnimations();
        mVisible = true;
        mGlowAlpha = getMaxGlowAlpha();
        ObjectAnimator scaleAnimator = ObjectAnimator.ofFloat(this, "glowScale",
                0f, GLOW_MAX_SCALE_FACTOR);
@@ -240,6 +270,12 @@ public class KeyButtonRipple extends Drawable {
        scaleAnimator.addListener(mAnimatorListener);
        scaleAnimator.start();
        mRunningAnimations.add(scaleAnimator);

        // With the delay, it could eventually animate the enter animation with no pressed state,
        // then immediately show the exit animation. If this is skipped there will be no ripple.
        if (mDelayTouchFeedback && !mPressed) {
            exitSoftware();
        }
    }

    private void exitSoftware() {
@@ -253,7 +289,16 @@ public class KeyButtonRipple extends Drawable {

    private void setPressedHardware(boolean pressed) {
        if (pressed) {
            if (mDelayTouchFeedback) {
                if (mRunningAnimations.isEmpty()) {
                    mHandler.removeCallbacksAndMessages(null);
                    mHandler.postDelayed(this::enterHardware, ViewConfiguration.getTapTimeout());
                } else if (mVisible) {
                    enterHardware();
                }
            } else {
                enterHardware();
            }
        } else {
            exitHardware();
        }
@@ -302,6 +347,7 @@ public class KeyButtonRipple extends Drawable {

    private void enterHardware() {
        cancelAnimations();
        mVisible = true;
        mDrawingHardwareGlow = true;
        setExtendStart(CanvasProperty.createFloat(getExtendSize() / 2));
        final RenderNodeAnimator startAnim = new RenderNodeAnimator(getExtendStart(),
@@ -343,6 +389,12 @@ public class KeyButtonRipple extends Drawable {
        mRunningAnimations.add(endAnim);

        invalidateSelf();

        // With the delay, it could eventually animate the enter animation with no pressed state,
        // then immediately show the exit animation. If this is skipped there will be no ripple.
        if (mDelayTouchFeedback && !mPressed) {
            exitHardware();
        }
    }

    private void exitHardware() {
@@ -366,6 +418,7 @@ public class KeyButtonRipple extends Drawable {
        public void onAnimationEnd(Animator animation) {
            mRunningAnimations.remove(animation);
            if (mRunningAnimations.isEmpty() && !mPressed) {
                mVisible = false;
                mDrawingHardwareGlow = false;
                invalidateSelf();
            }
+8 −27
Original line number Diff line number Diff line
@@ -65,7 +65,6 @@ public class KeyButtonView extends ImageView implements ButtonInterface {
    private int mTouchSlop;
    private int mTouchDownX;
    private int mTouchDownY;
    private boolean mIsPressed;
    private boolean mSupportsLongpress = true;
    private AudioManager mAudioManager;
    private boolean mGestureAborted;
@@ -78,7 +77,7 @@ public class KeyButtonView extends ImageView implements ButtonInterface {

    private final Runnable mCheckLongPress = new Runnable() {
        public void run() {
            if (mIsPressed) {
            if (isPressed()) {
                // Log.d("KeyButtonView", "longpressed: " + this);
                if (isLongClickable()) {
                    // Just an old-fashioned ImageView
@@ -89,12 +88,6 @@ public class KeyButtonView extends ImageView implements ButtonInterface {
                    sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
                    mLongClicked = true;
                }

                // Only when quick step is enabled, ripple will not be shown on touch down, then
                // show the ripple on touch up or on long press
                if (mLongClicked && mOverviewProxyService.getProxy() != null) {
                    setPressed(true);
                }
            }
        }
    };
@@ -214,9 +207,7 @@ public class KeyButtonView extends ImageView implements ButtonInterface {
            mGestureAborted = false;
        }
        if (mGestureAborted) {
            if (mIsPressed) {
            setPressed(false);
            }
            return false;
        }

@@ -224,6 +215,7 @@ public class KeyButtonView extends ImageView implements ButtonInterface {
            case MotionEvent.ACTION_DOWN:
                mDownTime = SystemClock.uptimeMillis();
                mLongClicked = false;
                setPressed(true);

                // Use raw X and Y to detect gestures in case a parent changes the x and y values
                mTouchDownX = (int) ev.getRawX();
@@ -234,10 +226,8 @@ public class KeyButtonView extends ImageView implements ButtonInterface {
                    // Provide the same haptic feedback that the system offers for virtual keys.
                    performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
                }
                mIsPressed = true;
                if (!isProxyConnected) {
                    playSoundEffect(SoundEffectConstants.CLICK);
                    setPressed(mIsPressed);
                }
                removeCallbacks(mCheckLongPress);
                postDelayed(mCheckLongPress, ViewConfiguration.getLongPressTimeout());
@@ -250,10 +240,7 @@ public class KeyButtonView extends ImageView implements ButtonInterface {
                if (exceededTouchSlopX || exceededTouchSlopY) {
                    // When quick step is enabled, prevent animating the ripple triggered by
                    // setPressed and decide to run it on touch up
                    mIsPressed = false;
                    if (!isProxyConnected) {
                        setPressed(mIsPressed);
                    }
                    setPressed(false);
                    removeCallbacks(mCheckLongPress);
                }
                break;
@@ -265,12 +252,11 @@ public class KeyButtonView extends ImageView implements ButtonInterface {
                removeCallbacks(mCheckLongPress);
                break;
            case MotionEvent.ACTION_UP:
                final boolean doIt = mIsPressed && !mLongClicked;
                final boolean doIt = isPressed() && !mLongClicked;
                setPressed(false);
                final boolean doHapticFeedback = (SystemClock.uptimeMillis() - mDownTime) > 150;
                if (isProxyConnected) {
                    if (doIt) {
                        // Animate the ripple in on touch up with setPressed and then out later
                        setPressed(true);
                        if (doHapticFeedback) {
                            mVibratorHelper.vibrate(VibrationEffect.EFFECT_TICK);
                        }
@@ -281,7 +267,6 @@ public class KeyButtonView extends ImageView implements ButtonInterface {
                    // and it feels weird to sometimes get a release haptic and other times not.
                    performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY_RELEASE);
                }
                setPressed(false);
                if (mCode != 0) {
                    if (doIt) {
                        // If there was a pending remote recents animation, then we need to
@@ -311,12 +296,6 @@ public class KeyButtonView extends ImageView implements ButtonInterface {
        mAudioManager.playSoundEffect(soundConstant, ActivityManager.getCurrentUser());
    }

    @Override
    public void setPressed(boolean pressed) {
        mIsPressed = pressed;
        super.setPressed(pressed);
    }

    public void sendEvent(int action, int flags) {
        sendEvent(action, flags, SystemClock.uptimeMillis());
    }
@@ -339,6 +318,7 @@ public class KeyButtonView extends ImageView implements ButtonInterface {
    @Override
    public void abortCurrentGesture() {
        setPressed(false);
        mRipple.abortDelayedRipple();
        mGestureAborted = true;
    }

@@ -357,6 +337,7 @@ public class KeyButtonView extends ImageView implements ButtonInterface {

    @Override
    public void setDelayTouchFeedback(boolean shouldDelay) {
        mRipple.setDelayTouchFeedback(shouldDelay);
    }

    @Override