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

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

Merge "Prevent ripple animation when swiping up for quick step"

parents fc957767 2fb239cd
Loading
Loading
Loading
Loading
+2 −54
Original line number Diff line number Diff line
@@ -26,11 +26,9 @@ import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.drawable.Drawable;
import android.os.Handler;
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;
@@ -58,17 +56,14 @@ 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<>();
@@ -82,10 +77,6 @@ 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();
@@ -220,16 +211,7 @@ 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++) {
@@ -238,21 +220,11 @@ 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();
        }
@@ -260,7 +232,6 @@ public class KeyButtonRipple extends Drawable {

    private void enterSoftware() {
        cancelAnimations();
        mVisible = true;
        mGlowAlpha = getMaxGlowAlpha();
        ObjectAnimator scaleAnimator = ObjectAnimator.ofFloat(this, "glowScale",
                0f, GLOW_MAX_SCALE_FACTOR);
@@ -269,12 +240,6 @@ 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() {
@@ -288,16 +253,7 @@ 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();
        }
@@ -346,7 +302,6 @@ public class KeyButtonRipple extends Drawable {

    private void enterHardware() {
        cancelAnimations();
        mVisible = true;
        mDrawingHardwareGlow = true;
        setExtendStart(CanvasProperty.createFloat(getExtendSize() / 2));
        final RenderNodeAnimator startAnim = new RenderNodeAnimator(getExtendStart(),
@@ -388,12 +343,6 @@ 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() {
@@ -417,7 +366,6 @@ public class KeyButtonRipple extends Drawable {
        public void onAnimationEnd(Animator animation) {
            mRunningAnimations.remove(animation);
            if (mRunningAnimations.isEmpty() && !mPressed) {
                mVisible = false;
                mDrawingHardwareGlow = false;
                invalidateSelf();
            }
+26 −7
Original line number Diff line number Diff line
@@ -67,6 +67,7 @@ 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;
@@ -79,7 +80,7 @@ public class KeyButtonView extends ImageView implements ButtonInterface {

    private final Runnable mCheckLongPress = new Runnable() {
        public void run() {
            if (isPressed()) {
            if (mIsPressed) {
                // Log.d("KeyButtonView", "longpressed: " + this);
                if (isLongClickable()) {
                    // Just an old-fashioned ImageView
@@ -90,6 +91,12 @@ 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);
                }
            }
        }
    };
@@ -216,7 +223,6 @@ public class KeyButtonView extends ImageView implements ButtonInterface {
            case MotionEvent.ACTION_DOWN:
                mDownTime = SystemClock.uptimeMillis();
                mLongClicked = false;
                setPressed(true);
                mTouchDownX = (int) ev.getX();
                mTouchDownY = (int) ev.getY();
                if (mCode != 0) {
@@ -225,6 +231,7 @@ 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) {
                    // Provide small vibration for quick step or immediate down feedback
                    AsyncTask.execute(() ->
@@ -232,6 +239,7 @@ public class KeyButtonView extends ImageView implements ButtonInterface {
                                    .get(VibrationEffect.EFFECT_TICK, false)));
                } else {
                    playSoundEffect(SoundEffectConstants.CLICK);
                    setPressed(mIsPressed);
                }
                removeCallbacks(mCheckLongPress);
                postDelayed(mCheckLongPress, ViewConfiguration.getLongPressTimeout());
@@ -242,7 +250,12 @@ public class KeyButtonView extends ImageView implements ButtonInterface {
                boolean exceededTouchSlopX = Math.abs(x - mTouchDownX) > mTouchSlop;
                boolean exceededTouchSlopY = Math.abs(y - mTouchDownY) > mTouchSlop;
                if (exceededTouchSlopX || exceededTouchSlopY) {
                    setPressed(false);
                    // 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);
                    }
                    removeCallbacks(mCheckLongPress);
                }
                break;
@@ -254,10 +267,11 @@ public class KeyButtonView extends ImageView implements ButtonInterface {
                removeCallbacks(mCheckLongPress);
                break;
            case MotionEvent.ACTION_UP:
                final boolean doIt = isPressed() && !mLongClicked;
                setPressed(false);
                final boolean doIt = mIsPressed && !mLongClicked;
                if (isProxyConnected) {
                    if (doIt) {
                        // Animate the ripple in on touch up with setPressed and then out later
                        setPressed(true);
                        performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
                        playSoundEffect(SoundEffectConstants.CLICK);
                    }
@@ -266,6 +280,7 @@ 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
@@ -295,6 +310,12 @@ 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());
    }
@@ -317,7 +338,6 @@ public class KeyButtonView extends ImageView implements ButtonInterface {
    @Override
    public void abortCurrentGesture() {
        setPressed(false);
        mRipple.abortDelayedRipple();
        mGestureAborted = true;
    }

@@ -336,7 +356,6 @@ public class KeyButtonView extends ImageView implements ButtonInterface {

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

    @Override