Loading packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java +2 −54 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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<>(); Loading @@ -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(); Loading Loading @@ -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++) { Loading @@ -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(); } Loading @@ -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); Loading @@ -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() { Loading @@ -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(); } Loading Loading @@ -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(), Loading Loading @@ -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() { Loading @@ -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(); } Loading packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java +26 −7 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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 Loading @@ -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); } } } }; Loading Loading @@ -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) { Loading @@ -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(() -> Loading @@ -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()); Loading @@ -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; Loading @@ -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); } Loading @@ -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 Loading Loading @@ -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()); } Loading @@ -317,7 +338,6 @@ public class KeyButtonView extends ImageView implements ButtonInterface { @Override public void abortCurrentGesture() { setPressed(false); mRipple.abortDelayedRipple(); mGestureAborted = true; } Loading @@ -336,7 +356,6 @@ public class KeyButtonView extends ImageView implements ButtonInterface { @Override public void setDelayTouchFeedback(boolean shouldDelay) { mRipple.setDelayTouchFeedback(shouldDelay); } @Override Loading Loading
packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java +2 −54 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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<>(); Loading @@ -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(); Loading Loading @@ -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++) { Loading @@ -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(); } Loading @@ -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); Loading @@ -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() { Loading @@ -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(); } Loading Loading @@ -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(), Loading Loading @@ -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() { Loading @@ -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(); } Loading
packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java +26 −7 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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 Loading @@ -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); } } } }; Loading Loading @@ -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) { Loading @@ -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(() -> Loading @@ -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()); Loading @@ -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; Loading @@ -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); } Loading @@ -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 Loading Loading @@ -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()); } Loading @@ -317,7 +338,6 @@ public class KeyButtonView extends ImageView implements ButtonInterface { @Override public void abortCurrentGesture() { setPressed(false); mRipple.abortDelayedRipple(); mGestureAborted = true; } Loading @@ -336,7 +356,6 @@ public class KeyButtonView extends ImageView implements ButtonInterface { @Override public void setDelayTouchFeedback(boolean shouldDelay) { mRipple.setDelayTouchFeedback(shouldDelay); } @Override Loading