KeyButtonRipple.java revision b9e290c7136fb7c76b7238426ccd598dec2d2643
1072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi/* 2072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi * Copyright (C) 2014 The Android Open Source Project 3072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi * 4072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi * Licensed under the Apache License, Version 2.0 (the "License"); 5072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi * you may not use this file except in compliance with the License. 6072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi * You may obtain a copy of the License at 7072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi * 8072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi * http://www.apache.org/licenses/LICENSE-2.0 9072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi * 10072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi * Unless required by applicable law or agreed to in writing, software 11072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi * distributed under the License is distributed on an "AS IS" BASIS, 12072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi * See the License for the specific language governing permissions and 14072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi * limitations under the License 15072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi */ 16072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi 17072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggipackage com.android.systemui.statusbar.policy; 18072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi 19072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggiimport android.animation.Animator; 20072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggiimport android.animation.AnimatorListenerAdapter; 21072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggiimport android.animation.ObjectAnimator; 22072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggiimport android.content.Context; 23072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggiimport android.graphics.Canvas; 24072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggiimport android.graphics.CanvasProperty; 25072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggiimport android.graphics.ColorFilter; 26072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggiimport android.graphics.Paint; 27072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggiimport android.graphics.PixelFormat; 28072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggiimport android.graphics.drawable.Drawable; 29072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggiimport android.view.HardwareCanvas; 30072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggiimport android.view.RenderNodeAnimator; 31072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggiimport android.view.View; 32072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggiimport android.view.animation.Interpolator; 33072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi 34072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggiimport com.android.systemui.R; 35072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggiimport com.android.systemui.statusbar.phone.PhoneStatusBar; 36072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi 37072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggiimport java.util.ArrayList; 38072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggiimport java.util.HashSet; 39072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi 40072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggipublic class KeyButtonRipple extends Drawable { 41072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi 42072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi private static final float GLOW_MAX_SCALE_FACTOR = 1.35f; 43072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi private static final float GLOW_MAX_ALPHA = 0.2f; 44072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi private static final int ANIMATION_DURATION_SCALE = 350; 45072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi private static final int ANIMATION_DURATION_FADE = 450; 46072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi 47072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi private Paint mRipplePaint; 48072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi private CanvasProperty<Float> mLeftProp; 49072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi private CanvasProperty<Float> mTopProp; 50072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi private CanvasProperty<Float> mRightProp; 51072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi private CanvasProperty<Float> mBottomProp; 52072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi private CanvasProperty<Float> mRxProp; 53072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi private CanvasProperty<Float> mRyProp; 54072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi private CanvasProperty<Paint> mPaintProp; 55072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi private float mGlowAlpha = 0f; 56072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi private float mGlowScale = 1f; 57072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi private boolean mPressed; 58072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi private boolean mDrawingHardwareGlow; 59072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi private int mMaxWidth; 60072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi 61072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi private final Interpolator mInterpolator = new LogInterpolator(); 62072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi private final Interpolator mAlphaExitInterpolator = PhoneStatusBar.ALPHA_OUT; 63072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi private boolean mSupportHardware; 64072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi private final View mTargetView; 65072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi 66072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi private final HashSet<Animator> mRunningAnimations = new HashSet<>(); 67072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi private final ArrayList<Animator> mTmpArray = new ArrayList<>(); 68072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi 69072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi public KeyButtonRipple(Context ctx, View targetView) { 70072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi mMaxWidth = ctx.getResources().getDimensionPixelSize(R.dimen.key_button_ripple_max_width); 71072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi mTargetView = targetView; 72072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi } 73072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi 74072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi private Paint getRipplePaint() { 75072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi if (mRipplePaint == null) { 76072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi mRipplePaint = new Paint(); 77072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi mRipplePaint.setAntiAlias(true); 78072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi mRipplePaint.setColor(0xffffffff); 79072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi } 80072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi return mRipplePaint; 81072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi } 82072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi 83072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi private void drawSoftware(Canvas canvas) { 84072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi if (mGlowAlpha > 0f) { 85072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi final Paint p = getRipplePaint(); 86072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi p.setAlpha((int)(mGlowAlpha * 255f)); 87072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi 88072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi final float w = getBounds().width(); 89072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi final float h = getBounds().height(); 90072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi final boolean horizontal = w > h; 91072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi final float diameter = getRippleSize() * mGlowScale; 92072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi final float radius = diameter * .5f; 93072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi final float cx = w * .5f; 94072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi final float cy = h * .5f; 95072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi final float rx = horizontal ? radius : cx; 96072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi final float ry = horizontal ? cy : radius; 97072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi final float corner = horizontal ? cy : cx; 98072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi 99072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi canvas.drawRoundRect(cx - rx, cy - ry, 100072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi cx + rx, cy + ry, 101072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi corner, corner, p); 102072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi } 103072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi } 104072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi 105072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi @Override 106072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi public void draw(Canvas canvas) { 107072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi mSupportHardware = canvas.isHardwareAccelerated(); 108072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi if (mSupportHardware) { 109072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi drawHardware((HardwareCanvas) canvas); 110072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi } else { 111072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi drawSoftware(canvas); 112072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi } 113072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi } 114072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi 115072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi @Override 116072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi public void setAlpha(int alpha) { 117072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi // Not supported. 118072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi } 119072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi 120072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi @Override 121072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi public void setColorFilter(ColorFilter cf) { 122072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi // Not supported. 123072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi } 124072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi 125072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi @Override 126072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi public int getOpacity() { 127072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi return PixelFormat.TRANSLUCENT; 128072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi } 129072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi 130072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi private boolean isHorizontal() { 131072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi return getBounds().width() > getBounds().height(); 132072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi } 133072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi 134072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi private void drawHardware(HardwareCanvas c) { 135072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi if (mDrawingHardwareGlow) { 136072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi c.drawRoundRect(mLeftProp, mTopProp, mRightProp, mBottomProp, mRxProp, mRyProp, 137072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi mPaintProp); 138072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi } 139072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi } 140072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi 141072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi public float getGlowAlpha() { 142072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi return mGlowAlpha; 143072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi } 144072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi 145072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi public void setGlowAlpha(float x) { 146072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi mGlowAlpha = x; 147072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi invalidateSelf(); 148072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi } 149072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi 150072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi public float getGlowScale() { 151072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi return mGlowScale; 152072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi } 153072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi 154072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi public void setGlowScale(float x) { 155072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi mGlowScale = x; 156072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi invalidateSelf(); 157072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi } 158072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi 159072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi @Override 160072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi protected boolean onStateChange(int[] state) { 161072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi boolean pressed = false; 162072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi for (int i = 0; i < state.length; i++) { 163072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi if (state[i] == android.R.attr.state_pressed) { 164072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi pressed = true; 165072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi break; 166072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi } 167072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi } 168072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi if (pressed != mPressed) { 169072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi setPressed(pressed); 170072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi mPressed = pressed; 171072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi return true; 172072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi } else { 173072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi return false; 174072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi } 175072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi } 176072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi 177072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi @Override 178b9e290c7136fb7c76b7238426ccd598dec2d2643Jorim Jaggi public void jumpToCurrentState() { 179b9e290c7136fb7c76b7238426ccd598dec2d2643Jorim Jaggi cancelAnimations(); 180b9e290c7136fb7c76b7238426ccd598dec2d2643Jorim Jaggi } 181b9e290c7136fb7c76b7238426ccd598dec2d2643Jorim Jaggi 182b9e290c7136fb7c76b7238426ccd598dec2d2643Jorim Jaggi @Override 183072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi public boolean isStateful() { 184072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi return true; 185072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi } 186072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi 187072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi public void setPressed(boolean pressed) { 188072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi if (mSupportHardware) { 189072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi setPressedHardware(pressed); 190072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi } else { 191072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi setPressedSoftware(pressed); 192072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi } 193072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi } 194072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi 195072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi private void cancelAnimations() { 196072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi mTmpArray.addAll(mRunningAnimations); 197072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi int size = mTmpArray.size(); 198072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi for (int i = 0; i < size; i++) { 199072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi Animator a = mTmpArray.get(i); 200072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi a.cancel(); 201072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi } 202072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi mTmpArray.clear(); 203072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi mRunningAnimations.clear(); 204072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi } 205072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi 206072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi private void setPressedSoftware(boolean pressed) { 207072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi if (pressed) { 208072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi enterSoftware(); 209072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi } else { 210072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi exitSoftware(); 211072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi } 212072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi } 213072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi 214072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi private void enterSoftware() { 215072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi cancelAnimations(); 216072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi mGlowAlpha = GLOW_MAX_ALPHA; 217072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi ObjectAnimator scaleAnimator = ObjectAnimator.ofFloat(this, "glowScale", 218072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi 0f, GLOW_MAX_SCALE_FACTOR); 219072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi scaleAnimator.setInterpolator(mInterpolator); 220072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi scaleAnimator.setDuration(ANIMATION_DURATION_SCALE); 221072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi scaleAnimator.addListener(mAnimatorListener); 222072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi scaleAnimator.start(); 223072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi mRunningAnimations.add(scaleAnimator); 224072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi } 225072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi 226072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi private void exitSoftware() { 227072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi ObjectAnimator alphaAnimator = ObjectAnimator.ofFloat(this, "glowAlpha", mGlowAlpha, 0f); 228072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi alphaAnimator.setInterpolator(mAlphaExitInterpolator); 229072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi alphaAnimator.setDuration(ANIMATION_DURATION_FADE); 230072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi alphaAnimator.addListener(mAnimatorListener); 231072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi alphaAnimator.start(); 232072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi mRunningAnimations.add(alphaAnimator); 233072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi } 234072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi 235072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi private void setPressedHardware(boolean pressed) { 236072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi if (pressed) { 237072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi enterHardware(); 238072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi } else { 239072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi exitHardware(); 240072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi } 241072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi } 242072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi 243072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi /** 244072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi * Sets the left/top property for the round rect to {@code prop} depending on whether we are 245072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi * horizontal or vertical mode. 246072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi */ 247072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi private void setExtendStart(CanvasProperty<Float> prop) { 248072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi if (isHorizontal()) { 249072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi mLeftProp = prop; 250072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi } else { 251072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi mTopProp = prop; 252072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi } 253072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi } 254072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi 255072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi private CanvasProperty<Float> getExtendStart() { 256072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi return isHorizontal() ? mLeftProp : mTopProp; 257072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi } 258072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi 259072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi /** 260072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi * Sets the right/bottom property for the round rect to {@code prop} depending on whether we are 261072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi * horizontal or vertical mode. 262072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi */ 263072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi private void setExtendEnd(CanvasProperty<Float> prop) { 264072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi if (isHorizontal()) { 265072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi mRightProp = prop; 266072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi } else { 267072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi mBottomProp = prop; 268072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi } 269072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi } 270072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi 271072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi private CanvasProperty<Float> getExtendEnd() { 272072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi return isHorizontal() ? mRightProp : mBottomProp; 273072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi } 274072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi 275072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi private int getExtendSize() { 276072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi return isHorizontal() ? getBounds().width() : getBounds().height(); 277072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi } 278072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi 279072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi private int getRippleSize() { 280072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi int size = isHorizontal() ? getBounds().width() : getBounds().height(); 281072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi return Math.min(size, mMaxWidth); 282072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi } 283072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi 284072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi private void enterHardware() { 285072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi cancelAnimations(); 286072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi mDrawingHardwareGlow = true; 287072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi setExtendStart(CanvasProperty.createFloat(getExtendSize() / 2)); 288072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi final RenderNodeAnimator startAnim = new RenderNodeAnimator(getExtendStart(), 289072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi getExtendSize()/2 - GLOW_MAX_SCALE_FACTOR * getRippleSize()/2); 290072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi startAnim.setDuration(ANIMATION_DURATION_SCALE); 291072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi startAnim.setInterpolator(mInterpolator); 292072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi startAnim.addListener(mAnimatorListener); 293072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi startAnim.setTarget(mTargetView); 294072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi 295072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi setExtendEnd(CanvasProperty.createFloat(getExtendSize() / 2)); 296072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi final RenderNodeAnimator endAnim = new RenderNodeAnimator(getExtendEnd(), 297072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi getExtendSize()/2 + GLOW_MAX_SCALE_FACTOR * getRippleSize()/2); 298072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi endAnim.setDuration(ANIMATION_DURATION_SCALE); 299072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi endAnim.setInterpolator(mInterpolator); 300072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi endAnim.addListener(mAnimatorListener); 301072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi endAnim.setTarget(mTargetView); 302072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi 303072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi if (isHorizontal()) { 304072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi mTopProp = CanvasProperty.createFloat(0f); 305072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi mBottomProp = CanvasProperty.createFloat(getBounds().height()); 306072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi mRxProp = CanvasProperty.createFloat(getBounds().height()/2); 307072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi mRyProp = CanvasProperty.createFloat(getBounds().height()/2); 308072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi } else { 309072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi mLeftProp = CanvasProperty.createFloat(0f); 310072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi mRightProp = CanvasProperty.createFloat(getBounds().width()); 311072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi mRxProp = CanvasProperty.createFloat(getBounds().width()/2); 312072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi mRyProp = CanvasProperty.createFloat(getBounds().width()/2); 313072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi } 314072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi 315072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi mGlowScale = GLOW_MAX_SCALE_FACTOR; 316072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi mGlowAlpha = GLOW_MAX_ALPHA; 317072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi mRipplePaint = getRipplePaint(); 318072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi mRipplePaint.setAlpha((int) (mGlowAlpha * 255)); 319072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi mPaintProp = CanvasProperty.createPaint(mRipplePaint); 320072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi 321072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi startAnim.start(); 322072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi endAnim.start(); 323072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi mRunningAnimations.add(startAnim); 324072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi mRunningAnimations.add(endAnim); 325072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi 326072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi invalidateSelf(); 327072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi } 328072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi 329072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi private void exitHardware() { 330072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi mPaintProp = CanvasProperty.createPaint(getRipplePaint()); 331072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi final RenderNodeAnimator opacityAnim = new RenderNodeAnimator(mPaintProp, 332072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi RenderNodeAnimator.PAINT_ALPHA, 0); 333072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi opacityAnim.setDuration(ANIMATION_DURATION_FADE); 334072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi opacityAnim.setInterpolator(mAlphaExitInterpolator); 335072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi opacityAnim.addListener(mAnimatorListener); 336072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi opacityAnim.setTarget(mTargetView); 337072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi 338072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi opacityAnim.start(); 339072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi mRunningAnimations.add(opacityAnim); 340072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi 341072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi invalidateSelf(); 342072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi } 343072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi 344072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi private final AnimatorListenerAdapter mAnimatorListener = 345072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi new AnimatorListenerAdapter() { 346072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi @Override 347072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi public void onAnimationEnd(Animator animation) { 348072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi mRunningAnimations.remove(animation); 349072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi if (mRunningAnimations.isEmpty() && !mPressed) { 350072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi mDrawingHardwareGlow = false; 351072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi invalidateSelf(); 352072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi } 353072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi } 354072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi }; 355072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi 356072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi /** 357072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi * Interpolator with a smooth log deceleration 358072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi */ 359072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi private static final class LogInterpolator implements Interpolator { 360072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi @Override 361072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi public float getInterpolation(float input) { 362072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi return 1 - (float) Math.pow(400, -input * 1.4); 363072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi } 364072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi } 365072707dfad1da6f49f4d3ce58ca104f6c46a7266Jorim Jaggi} 366