12fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi/* 22fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi * Copyright (C) 2014 The Android Open Source Project 32fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi * 42fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi * Licensed under the Apache License, Version 2.0 (the "License"); 52fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi * you may not use this file except in compliance with the License. 62fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi * You may obtain a copy of the License at 72fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi * 82fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi * http://www.apache.org/licenses/LICENSE-2.0 92fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi * 102fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi * Unless required by applicable law or agreed to in writing, software 112fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi * distributed under the License is distributed on an "AS IS" BASIS, 122fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 132fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi * See the License for the specific language governing permissions and 142fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi * limitations under the License 152fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi */ 162fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi 172fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggipackage com.android.systemui.assist; 182fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi 192fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggiimport android.animation.Animator; 202fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggiimport android.animation.AnimatorListenerAdapter; 212fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggiimport android.animation.ValueAnimator; 222fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggiimport android.content.Context; 232fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggiimport android.graphics.Canvas; 242fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggiimport android.graphics.Outline; 252fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggiimport android.graphics.Paint; 262fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggiimport android.graphics.Rect; 272fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggiimport android.util.AttributeSet; 282fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggiimport android.view.View; 292fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggiimport android.view.ViewOutlineProvider; 302fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggiimport android.view.animation.Interpolator; 312fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggiimport android.view.animation.OvershootInterpolator; 322fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggiimport android.widget.FrameLayout; 332fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggiimport android.widget.ImageView; 342fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi 35c0d7058b14c24cd07912f5629c26b39b7b4673d5Winsonimport com.android.systemui.Interpolators; 362fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggiimport com.android.systemui.R; 372fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi 382fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggipublic class AssistOrbView extends FrameLayout { 392fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi 402fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi private final int mCircleMinSize; 412fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi private final int mBaseMargin; 422fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi private final int mStaticOffset; 432fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi private final Paint mBackgroundPaint = new Paint(); 442fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi private final Rect mCircleRect = new Rect(); 452fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi private final Rect mStaticRect = new Rect(); 462fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi private final Interpolator mOvershootInterpolator = new OvershootInterpolator(); 472fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi 482fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi private boolean mClipToOutline; 492fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi private final int mMaxElevation; 502fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi private float mOutlineAlpha; 512fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi private float mOffset; 522fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi private float mCircleSize; 532fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi private ImageView mLogo; 542fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi private float mCircleAnimationEndValue; 552fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi 562fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi private ValueAnimator mOffsetAnimator; 572fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi private ValueAnimator mCircleAnimator; 582fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi 592fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi private ValueAnimator.AnimatorUpdateListener mCircleUpdateListener 602fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi = new ValueAnimator.AnimatorUpdateListener() { 612fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi @Override 622fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi public void onAnimationUpdate(ValueAnimator animation) { 632fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi applyCircleSize((float) animation.getAnimatedValue()); 642fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi updateElevation(); 652fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi } 662fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi }; 672fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi private AnimatorListenerAdapter mClearAnimatorListener = new AnimatorListenerAdapter() { 682fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi @Override 692fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi public void onAnimationEnd(Animator animation) { 702fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi mCircleAnimator = null; 712fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi } 722fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi }; 732fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi private ValueAnimator.AnimatorUpdateListener mOffsetUpdateListener 742fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi = new ValueAnimator.AnimatorUpdateListener() { 752fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi @Override 762fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi public void onAnimationUpdate(ValueAnimator animation) { 772fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi mOffset = (float) animation.getAnimatedValue(); 782fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi updateLayout(); 792fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi } 802fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi }; 812fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi 822fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi 832fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi public AssistOrbView(Context context) { 842fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi this(context, null); 852fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi } 862fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi 872fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi public AssistOrbView(Context context, AttributeSet attrs) { 882fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi this(context, attrs, 0); 892fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi } 902fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi 912fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi public AssistOrbView(Context context, AttributeSet attrs, int defStyleAttr) { 922fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi this(context, attrs, defStyleAttr, 0); 932fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi } 942fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi 952fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi public AssistOrbView(Context context, AttributeSet attrs, int defStyleAttr, 962fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi int defStyleRes) { 972fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi super(context, attrs, defStyleAttr, defStyleRes); 982fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi setOutlineProvider(new ViewOutlineProvider() { 992fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi @Override 1002fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi public void getOutline(View view, Outline outline) { 1012fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi if (mCircleSize > 0.0f) { 1022fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi outline.setOval(mCircleRect); 1032fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi } else { 1042fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi outline.setEmpty(); 1052fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi } 1062fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi outline.setAlpha(mOutlineAlpha); 1072fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi } 1082fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi }); 1092fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi setWillNotDraw(false); 1102fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi mCircleMinSize = context.getResources().getDimensionPixelSize( 1112fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi R.dimen.assist_orb_size); 1122fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi mBaseMargin = context.getResources().getDimensionPixelSize( 1132fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi R.dimen.assist_orb_base_margin); 1142fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi mStaticOffset = context.getResources().getDimensionPixelSize( 1152fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi R.dimen.assist_orb_travel_distance); 1162fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi mMaxElevation = context.getResources().getDimensionPixelSize( 1172fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi R.dimen.assist_orb_elevation); 1182fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi mBackgroundPaint.setAntiAlias(true); 1192fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi mBackgroundPaint.setColor(getResources().getColor(R.color.assist_orb_color)); 1202fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi } 1212fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi 1222fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi public ImageView getLogo() { 1232fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi return mLogo; 1242fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi } 1252fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi 1262fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi @Override 1272fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi protected void onDraw(Canvas canvas) { 1282fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi super.onDraw(canvas); 1292fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi drawBackground(canvas); 1302fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi } 1312fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi 1322fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi private void drawBackground(Canvas canvas) { 1332fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi canvas.drawCircle(mCircleRect.centerX(), mCircleRect.centerY(), mCircleSize / 2, 1342fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi mBackgroundPaint); 1352fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi } 1362fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi 1372fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi @Override 1382fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi protected void onFinishInflate() { 1392fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi super.onFinishInflate(); 14051efddbd3bb304de2dd47fa8cd1114ac555958bbAlan Viverette mLogo = findViewById(R.id.search_logo); 1412fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi } 1422fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi 1432fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi @Override 1442fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi protected void onLayout(boolean changed, int l, int t, int r, int b) { 1452fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi mLogo.layout(0, 0, mLogo.getMeasuredWidth(), mLogo.getMeasuredHeight()); 1462fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi if (changed) { 1472fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi updateCircleRect(mStaticRect, mStaticOffset, true); 1482fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi } 1492fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi } 1502fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi 1512fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi public void animateCircleSize(float circleSize, long duration, 1522fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi long startDelay, Interpolator interpolator) { 1532fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi if (circleSize == mCircleAnimationEndValue) { 1542fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi return; 1552fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi } 1562fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi if (mCircleAnimator != null) { 1572fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi mCircleAnimator.cancel(); 1582fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi } 1592fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi mCircleAnimator = ValueAnimator.ofFloat(mCircleSize, circleSize); 1602fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi mCircleAnimator.addUpdateListener(mCircleUpdateListener); 1612fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi mCircleAnimator.addListener(mClearAnimatorListener); 1622fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi mCircleAnimator.setInterpolator(interpolator); 1632fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi mCircleAnimator.setDuration(duration); 1642fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi mCircleAnimator.setStartDelay(startDelay); 1652fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi mCircleAnimator.start(); 1662fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi mCircleAnimationEndValue = circleSize; 1672fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi } 1682fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi 1692fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi private void applyCircleSize(float circleSize) { 1702fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi mCircleSize = circleSize; 1712fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi updateLayout(); 1722fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi } 1732fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi 1742fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi private void updateElevation() { 1752fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi float t = (mStaticOffset - mOffset) / (float) mStaticOffset; 1762fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi t = 1.0f - Math.max(t, 0.0f); 1772fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi float offset = t * mMaxElevation; 1782fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi setElevation(offset); 1792fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi } 1802fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi 1812fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi /** 1822fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi * Animates the offset to the edge of the screen. 1832fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi * 1842fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi * @param offset The offset to apply. 1852fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi * @param startDelay The desired start delay if animated. 1862fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi * 1872fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi * @param interpolator The desired interpolator if animated. If null, 1882fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi * a default interpolator will be taken designed for appearing or 1892fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi * disappearing. 1902fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi */ 1912fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi private void animateOffset(float offset, long duration, long startDelay, 1922fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi Interpolator interpolator) { 1932fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi if (mOffsetAnimator != null) { 1942fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi mOffsetAnimator.removeAllListeners(); 1952fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi mOffsetAnimator.cancel(); 1962fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi } 1972fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi mOffsetAnimator = ValueAnimator.ofFloat(mOffset, offset); 1982fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi mOffsetAnimator.addUpdateListener(mOffsetUpdateListener); 1992fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi mOffsetAnimator.addListener(new AnimatorListenerAdapter() { 2002fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi @Override 2012fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi public void onAnimationEnd(Animator animation) { 2022fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi mOffsetAnimator = null; 2032fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi } 2042fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi }); 2052fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi mOffsetAnimator.setInterpolator(interpolator); 2062fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi mOffsetAnimator.setStartDelay(startDelay); 2072fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi mOffsetAnimator.setDuration(duration); 2082fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi mOffsetAnimator.start(); 2092fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi } 2102fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi 2112fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi private void updateLayout() { 2122fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi updateCircleRect(); 2132fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi updateLogo(); 2142fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi invalidateOutline(); 2152fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi invalidate(); 2162fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi updateClipping(); 2172fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi } 2182fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi 2192fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi private void updateClipping() { 2202fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi boolean clip = mCircleSize < mCircleMinSize; 2212fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi if (clip != mClipToOutline) { 2222fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi setClipToOutline(clip); 2232fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi mClipToOutline = clip; 2242fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi } 2252fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi } 2262fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi 2272fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi private void updateLogo() { 2282fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi float translationX = (mCircleRect.left + mCircleRect.right) / 2.0f - mLogo.getWidth() / 2.0f; 2292fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi float translationY = (mCircleRect.top + mCircleRect.bottom) / 2.0f 2302fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi - mLogo.getHeight() / 2.0f - mCircleMinSize / 7f; 2312fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi float t = (mStaticOffset - mOffset) / (float) mStaticOffset; 2322fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi translationY += t * mStaticOffset * 0.1f; 2332fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi float alpha = 1.0f-t; 2342fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi alpha = Math.max((alpha - 0.5f) * 2.0f, 0); 2352fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi mLogo.setImageAlpha((int) (alpha * 255)); 2362fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi mLogo.setTranslationX(translationX); 2372fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi mLogo.setTranslationY(translationY); 2382fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi } 2392fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi 2402fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi private void updateCircleRect() { 2412fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi updateCircleRect(mCircleRect, mOffset, false); 2422fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi } 2432fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi 2442fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi private void updateCircleRect(Rect rect, float offset, boolean useStaticSize) { 2452fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi int left, top; 2462fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi float circleSize = useStaticSize ? mCircleMinSize : mCircleSize; 2472fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi left = (int) (getWidth() - circleSize) / 2; 2482fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi top = (int) (getHeight() - circleSize / 2 - mBaseMargin - offset); 2492fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi rect.set(left, top, (int) (left + circleSize), (int) (top + circleSize)); 2502fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi } 2512fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi 2522fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi public void startExitAnimation(long delay) { 253c18010f6720f606003cde3cd376ddacaca30f6e5Selim Cinek animateCircleSize(0, 200, delay, Interpolators.FAST_OUT_LINEAR_IN); 254c18010f6720f606003cde3cd376ddacaca30f6e5Selim Cinek animateOffset(0, 200, delay, Interpolators.FAST_OUT_LINEAR_IN); 2552fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi } 2562fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi 2572fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi public void startEnterAnimation() { 2582fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi applyCircleSize(0); 2592fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi post(new Runnable() { 2602fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi @Override 2612fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi public void run() { 2622fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi animateCircleSize(mCircleMinSize, 300, 0 /* delay */, mOvershootInterpolator); 263c18010f6720f606003cde3cd376ddacaca30f6e5Selim Cinek animateOffset(mStaticOffset, 400, 0 /* delay */, Interpolators.LINEAR_OUT_SLOW_IN); 2642fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi } 2652fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi }); 2662fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi } 2672fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi 2682fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi public void reset() { 2692fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi mClipToOutline = false; 2702fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi mBackgroundPaint.setAlpha(255); 2712fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi mOutlineAlpha = 1.0f; 2722fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi } 2732fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi 2742fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi @Override 2752fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi public boolean hasOverlappingRendering() { 2762fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi // not really true but it's ok during an animation, as it's never permanent 2772fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi return false; 2782fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi } 2792fdeeabe78b0f54f3163b1b3741ac813828b3511Jorim Jaggi} 280