12e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos/*
22e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos * Copyright (C) 2014 The Android Open Source Project
32e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos *
42e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos * Licensed under the Apache License, Version 2.0 (the "License");
52e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos * you may not use this file except in compliance with the License.
62e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos * You may obtain a copy of the License at
72e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos *
82e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos *      http://www.apache.org/licenses/LICENSE-2.0
92e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos *
102e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos * Unless required by applicable law or agreed to in writing, software
112e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos * distributed under the License is distributed on an "AS IS" BASIS,
122e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos * See the License for the specific language governing permissions and
142e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos * limitations under the License
152e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos */
162e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos
172e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roospackage com.android.systemui.statusbar.phone;
182e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos
192e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roosimport android.animation.Animator;
202e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roosimport android.animation.AnimatorListenerAdapter;
212e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roosimport android.animation.AnimatorSet;
222e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roosimport android.animation.ValueAnimator;
232e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roosimport android.content.Context;
242e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roosimport android.content.res.Resources;
252e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roosimport android.graphics.Canvas;
262e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roosimport android.graphics.Color;
272e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roosimport android.graphics.ColorFilter;
282e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roosimport android.graphics.Paint;
292e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roosimport android.graphics.PixelFormat;
302e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roosimport android.graphics.Rect;
312e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roosimport android.graphics.drawable.Drawable;
322e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roosimport android.view.animation.Interpolator;
332e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos
34c0d7058b14c24cd07912f5629c26b39b7b4673d5Winsonimport com.android.systemui.Interpolators;
35c18010f6720f606003cde3cd376ddacaca30f6e5Selim Cinekimport com.android.systemui.R;
36c18010f6720f606003cde3cd376ddacaca30f6e5Selim Cinek
372e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roospublic class TrustDrawable extends Drawable {
382e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos
392e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos    private static final long ENTERING_FROM_UNSET_START_DELAY = 200;
402e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos    private static final long VISIBLE_DURATION = 1000;
412e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos    private static final long EXIT_DURATION = 500;
422e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos    private static final long ENTER_DURATION = 500;
432e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos
442e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos    private static final int ALPHA_VISIBLE_MIN = 0x26;
452e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos    private static final int ALPHA_VISIBLE_MAX = 0x4c;
462e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos
472e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos    private static final int STATE_UNSET = -1;
482e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos    private static final int STATE_GONE = 0;
492e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos    private static final int STATE_ENTERING = 1;
502e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos    private static final int STATE_VISIBLE = 2;
512e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos    private static final int STATE_EXITING = 3;
522e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos
532e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos    private int mAlpha;
542e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos    private boolean mAnimating;
552e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos
562e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos    private int mCurAlpha;
572e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos    private float mCurInnerRadius;
582e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos    private Animator mCurAnimator;
592e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos    private int mState = STATE_UNSET;
602e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos    private Paint mPaint;
612e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos    private boolean mTrustManaged;
622e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos
632e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos    private final float mInnerRadiusVisibleMin;
642e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos    private final float mInnerRadiusVisibleMax;
652e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos    private final float mInnerRadiusExit;
662e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos    private final float mInnerRadiusEnter;
672e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos    private final float mThickness;
682e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos
692e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos    private final Animator mVisibleAnimator;
702e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos
712e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos    public TrustDrawable(Context context) {
722e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos        Resources r = context.getResources();
732e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos        mInnerRadiusVisibleMin = r.getDimension(R.dimen.trust_circle_inner_radius_visible_min);
742e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos        mInnerRadiusVisibleMax = r.getDimension(R.dimen.trust_circle_inner_radius_visible_max);
752e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos        mInnerRadiusExit = r.getDimension(R.dimen.trust_circle_inner_radius_exit);
762e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos        mInnerRadiusEnter = r.getDimension(R.dimen.trust_circle_inner_radius_enter);
772e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos        mThickness = r.getDimension(R.dimen.trust_circle_thickness);
782e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos
792e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos        mCurInnerRadius = mInnerRadiusEnter;
802e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos
812e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos        mVisibleAnimator = makeVisibleAnimator();
822e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos
832e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos        mPaint = new Paint();
842e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos        mPaint.setStyle(Paint.Style.STROKE);
852e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos        mPaint.setColor(Color.WHITE);
862e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos        mPaint.setAntiAlias(true);
872e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos        mPaint.setStrokeWidth(mThickness);
882e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos    }
892e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos
902e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos    @Override
912e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos    public void draw(Canvas canvas) {
922e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos        int newAlpha = (mCurAlpha * mAlpha) / 256;
932e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos        if (newAlpha == 0) {
942e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos            return;
952e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos        }
962e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos        final Rect r = getBounds();
972e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos        mPaint.setAlpha(newAlpha);
982e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos        canvas.drawCircle(r.exactCenterX(), r.exactCenterY(), mCurInnerRadius, mPaint);
992e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos    }
1002e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos
1012e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos    @Override
1022e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos    public void setAlpha(int alpha) {
1032e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos        mAlpha = alpha;
1042e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos    }
1052e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos
1062e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos    @Override
1072e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos    public int getAlpha() {
1082e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos        return mAlpha;
1092e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos    }
1102e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos
1112e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos    @Override
112bd3bfc5285dcacff0a69fecf3baeeeb90d887a58Chris Craik    public void setColorFilter(ColorFilter colorFilter) {
1132e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos        throw new UnsupportedOperationException("not implemented");
1142e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos    }
1152e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos
1162e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos    @Override
1172e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos    public int getOpacity() {
1182e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos        return PixelFormat.TRANSLUCENT;
1192e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos    }
1202e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos
1212e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos    public void start() {
1222e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos        if (!mAnimating) {
1232e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos            mAnimating = true;
1242e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos            updateState(true);
1251540da4624ebdf674784a970892d4d4b7b64e775Adrian Roos            invalidateSelf();
1262e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos        }
1272e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos    }
1282e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos
1292e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos    public void stop() {
1302e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos        if (mAnimating) {
1312e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos            mAnimating = false;
1322e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos            if (mCurAnimator != null) {
1332e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos                mCurAnimator.cancel();
1342e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos                mCurAnimator = null;
1352e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos            }
1362e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos            mState = STATE_UNSET;
1372e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos            mCurAlpha = 0;
1382e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos            mCurInnerRadius = mInnerRadiusEnter;
1391540da4624ebdf674784a970892d4d4b7b64e775Adrian Roos            invalidateSelf();
1402e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos        }
1412e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos    }
1422e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos
1432e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos    public void setTrustManaged(boolean trustManaged) {
1442e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos        if (trustManaged == mTrustManaged && mState != STATE_UNSET) return;
1452e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos        mTrustManaged = trustManaged;
1461540da4624ebdf674784a970892d4d4b7b64e775Adrian Roos        updateState(true);
1472e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos    }
1482e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos
1491540da4624ebdf674784a970892d4d4b7b64e775Adrian Roos    private void updateState(boolean allowTransientState) {
1501540da4624ebdf674784a970892d4d4b7b64e775Adrian Roos        if (!mAnimating) {
1511540da4624ebdf674784a970892d4d4b7b64e775Adrian Roos            return;
1521540da4624ebdf674784a970892d4d4b7b64e775Adrian Roos        }
1531540da4624ebdf674784a970892d4d4b7b64e775Adrian Roos
1542e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos        int nextState = mState;
1552e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos        if (mState == STATE_UNSET) {
1562e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos            nextState = mTrustManaged ? STATE_ENTERING : STATE_GONE;
1572e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos        } else if (mState == STATE_GONE) {
1582e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos            if (mTrustManaged) nextState = STATE_ENTERING;
1592e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos        } else if (mState == STATE_ENTERING) {
1602e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos            if (!mTrustManaged) nextState = STATE_EXITING;
1612e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos        } else if (mState == STATE_VISIBLE) {
1622e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos            if (!mTrustManaged) nextState = STATE_EXITING;
1632e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos        } else if (mState == STATE_EXITING) {
1642e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos            if (mTrustManaged) nextState = STATE_ENTERING;
1652e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos        }
1661540da4624ebdf674784a970892d4d4b7b64e775Adrian Roos        if (!allowTransientState) {
1672e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos            if (nextState == STATE_ENTERING) nextState = STATE_VISIBLE;
1682e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos            if (nextState == STATE_EXITING) nextState = STATE_GONE;
1692e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos        }
1702e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos
1712e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos        if (nextState != mState) {
1722e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos            if (mCurAnimator != null) {
1732e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos                mCurAnimator.cancel();
1742e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos                mCurAnimator = null;
1752e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos            }
1762e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos
1772e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos            if (nextState == STATE_GONE) {
1782e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos                mCurAlpha = 0;
1792e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos                mCurInnerRadius = mInnerRadiusEnter;
1802e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos            } else if (nextState == STATE_ENTERING) {
1812e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos                mCurAnimator = makeEnterAnimator(mCurInnerRadius, mCurAlpha);
1822e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos                if (mState == STATE_UNSET) {
1832e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos                    mCurAnimator.setStartDelay(ENTERING_FROM_UNSET_START_DELAY);
1842e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos                }
1852e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos            } else if (nextState == STATE_VISIBLE) {
1862e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos                mCurAlpha = ALPHA_VISIBLE_MAX;
1872e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos                mCurInnerRadius = mInnerRadiusVisibleMax;
1882e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos                mCurAnimator = mVisibleAnimator;
1892e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos            } else if (nextState == STATE_EXITING) {
1902e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos                mCurAnimator = makeExitAnimator(mCurInnerRadius, mCurAlpha);
1912e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos            }
1922e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos
1932e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos            mState = nextState;
1942e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos            if (mCurAnimator != null) {
1952e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos                mCurAnimator.start();
1962e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos            }
1971540da4624ebdf674784a970892d4d4b7b64e775Adrian Roos            invalidateSelf();
1982e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos        }
1992e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos    }
2002e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos
2012e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos    private Animator makeVisibleAnimator() {
2022e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos        return makeAnimators(mInnerRadiusVisibleMax, mInnerRadiusVisibleMin,
2032e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos                ALPHA_VISIBLE_MAX, ALPHA_VISIBLE_MIN, VISIBLE_DURATION,
204c18010f6720f606003cde3cd376ddacaca30f6e5Selim Cinek                Interpolators.ACCELERATE_DECELERATE,
2052e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos                true /* repeating */, false /* stateUpdateListener */);
2062e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos    }
2072e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos
2082e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos    private Animator makeEnterAnimator(float radius, int alpha) {
2092e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos        return makeAnimators(radius, mInnerRadiusVisibleMax,
210c18010f6720f606003cde3cd376ddacaca30f6e5Selim Cinek                alpha, ALPHA_VISIBLE_MAX, ENTER_DURATION, Interpolators.LINEAR_OUT_SLOW_IN,
2112e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos                false /* repeating */, true /* stateUpdateListener */);
2122e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos    }
2132e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos
2142e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos    private Animator makeExitAnimator(float radius, int alpha) {
2152e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos        return makeAnimators(radius, mInnerRadiusExit,
216c18010f6720f606003cde3cd376ddacaca30f6e5Selim Cinek                alpha, 0, EXIT_DURATION, Interpolators.FAST_OUT_SLOW_IN,
2172e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos                false /* repeating */, true /* stateUpdateListener */);
2182e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos    }
2192e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos
2202e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos    private Animator makeAnimators(float startRadius, float endRadius,
2212e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos            int startAlpha, int endAlpha, long duration, Interpolator interpolator,
2222e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos            boolean repeating, boolean stateUpdateListener) {
2232e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos        ValueAnimator alphaAnimator = configureAnimator(
2242e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos                ValueAnimator.ofInt(startAlpha, endAlpha),
2252e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos                duration, mAlphaUpdateListener, interpolator, repeating);
2262e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos        ValueAnimator sizeAnimator = configureAnimator(
2272e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos                ValueAnimator.ofFloat(startRadius, endRadius),
2282e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos                duration, mRadiusUpdateListener, interpolator, repeating);
2292e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos
2302e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos        AnimatorSet set = new AnimatorSet();
2312e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos        set.playTogether(alphaAnimator, sizeAnimator);
2322e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos        if (stateUpdateListener) {
2332e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos            set.addListener(new StateUpdateAnimatorListener());
2342e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos        }
2352e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos        return set;
2362e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos    }
2372e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos
2382e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos    private ValueAnimator configureAnimator(ValueAnimator animator, long duration,
2392e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos            ValueAnimator.AnimatorUpdateListener updateListener, Interpolator interpolator,
2402e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos            boolean repeating) {
2412e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos        animator.setDuration(duration);
2422e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos        animator.addUpdateListener(updateListener);
2432e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos        animator.setInterpolator(interpolator);
2442e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos        if (repeating) {
2452e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos            animator.setRepeatCount(ValueAnimator.INFINITE);
2462e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos            animator.setRepeatMode(ValueAnimator.REVERSE);
2472e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos        }
2482e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos        return animator;
2492e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos    }
2502e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos
2512e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos    private final ValueAnimator.AnimatorUpdateListener mAlphaUpdateListener =
2522e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos            new ValueAnimator.AnimatorUpdateListener() {
2532e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos        @Override
2542e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos        public void onAnimationUpdate(ValueAnimator animation) {
2552e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos            mCurAlpha = (int) animation.getAnimatedValue();
2562e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos            invalidateSelf();
2572e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos        }
2582e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos    };
2592e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos
2602e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos    private final ValueAnimator.AnimatorUpdateListener mRadiusUpdateListener =
2612e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos            new ValueAnimator.AnimatorUpdateListener() {
2622e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos        @Override
2632e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos        public void onAnimationUpdate(ValueAnimator animation) {
2642e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos            mCurInnerRadius = (float) animation.getAnimatedValue();
2652e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos            invalidateSelf();
2662e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos        }
2672e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos    };
2682e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos
2692e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos    private class StateUpdateAnimatorListener extends AnimatorListenerAdapter {
2702e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos        boolean mCancelled;
2712e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos
2722e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos        @Override
2732e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos        public void onAnimationStart(Animator animation) {
2742e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos            mCancelled = false;
2752e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos        }
2762e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos
2772e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos        @Override
2782e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos        public void onAnimationCancel(Animator animation) {
2792e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos            mCancelled = true;
2802e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos        }
2812e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos
2822e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos        @Override
2832e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos        public void onAnimationEnd(Animator animation) {
2842e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos            if (!mCancelled) {
2852e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos                updateState(false);
2862e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos            }
2872e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos        }
2882e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos    }
2892e3ccbb37e21eb40308f83fb185209773147f78dAdrian Roos}
290