1d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague/* 2d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague * Copyright (C) 2014 The Android Open Source Project 3d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague * 4d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague * Licensed under the Apache License, Version 2.0 (the "License"); 5d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague * you may not use this file except in compliance with the License. 6d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague * You may obtain a copy of the License at 7d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague * 8d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague * http://www.apache.org/licenses/LICENSE-2.0 9d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague * 10d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague * Unless required by applicable law or agreed to in writing, software 11d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague * distributed under the License is distributed on an "AS IS" BASIS, 12d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague * See the License for the specific language governing permissions and 14d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague * limitations under the License. 15d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague */ 16d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague 17d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Spraguepackage com.android.camera.ui; 18d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague 19d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Spragueimport android.animation.ValueAnimator; 20d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Spragueimport android.graphics.Canvas; 21d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Spragueimport android.graphics.ColorFilter; 22d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Spragueimport android.graphics.Paint; 23d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Spragueimport android.graphics.PixelFormat; 24d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Spragueimport android.graphics.drawable.Drawable; 25d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague 26d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Spragueimport com.android.camera.util.Gusterpolator; 27d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague 28d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Spraguepublic class AnimatedCircleDrawable extends Drawable { 29d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague private static final int CIRCLE_ANIM_DURATION_MS = 300; 30d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague private static int DRAWABLE_MAX_LEVEL = 10000; 31d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague 32d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague private int mCanvasWidth; 33d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague private int mCanvasHeight; 34d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague 35d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague private int mAlpha = 0xff; 36d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague private int mColor; 37d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague private Paint mPaint; 38d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague private int mRadius; 39d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague private int mSmallRadiusTarget; 40d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague 41d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague public AnimatedCircleDrawable(int smallRadiusTarget) { 42d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague mPaint = new Paint(); 43d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague mPaint.setAntiAlias(true); 44d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague mSmallRadiusTarget = smallRadiusTarget; 45d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague } 46d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague 47d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague public void setColor(int color) { 48d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague mColor = color; 49d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague updatePaintColor(); 50d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague } 51d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague 52d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague private void updatePaintColor() { 53d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague int paintColor = (mAlpha << 24) | (mColor & 0x00ffffff); 54d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague mPaint.setColor(paintColor); 55d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague invalidateSelf(); 56d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague } 57d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague 58d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague // abstract overrides 59d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague @Override 60d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague public int getOpacity() { 61d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague return PixelFormat.TRANSLUCENT; 62d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague } 63d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague 64d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague @Override 65d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague public void setAlpha(int alpha) { 66d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague mAlpha = alpha; 67d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague updatePaintColor(); 68d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague } 69d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague 70d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague @Override 71d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague public void setColorFilter(ColorFilter cf) { 72d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague //TODO support this? 73d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague } 74d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague // end abstract overrides 75d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague 76d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague @Override 77d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague public boolean onLevelChange(int level) { 78c5ecbd6e0a6c2a2d93fc58f0ba3d273249b06da2Spike Sprague if (level != getLevel()) { 79c5ecbd6e0a6c2a2d93fc58f0ba3d273249b06da2Spike Sprague invalidateSelf(); 80c5ecbd6e0a6c2a2d93fc58f0ba3d273249b06da2Spike Sprague return true; 81c5ecbd6e0a6c2a2d93fc58f0ba3d273249b06da2Spike Sprague } 82c5ecbd6e0a6c2a2d93fc58f0ba3d273249b06da2Spike Sprague return false; 83d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague } 84d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague 85d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague public void animateToSmallRadius() { 86d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague int smallLevel = map(mSmallRadiusTarget, 87d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague 0, diagonalLength(mCanvasWidth, mCanvasHeight)/2, 88d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague 0, DRAWABLE_MAX_LEVEL); 89d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague final ValueAnimator animator = 90d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague ValueAnimator.ofInt(getLevel(), smallLevel); 91d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague animator.setDuration(CIRCLE_ANIM_DURATION_MS); 92d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague animator.setInterpolator(Gusterpolator.INSTANCE); 93d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 94d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague @Override 95d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague public void onAnimationUpdate(ValueAnimator animation) { 96d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague setLevel((Integer) animation.getAnimatedValue()); 97d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague } 98d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague }); 99d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague animator.start(); 100d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague } 101d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague 102d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague public void animateToFullSize() { 103d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague final ValueAnimator animator = 104d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague ValueAnimator.ofInt(getLevel(), DRAWABLE_MAX_LEVEL); 105d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague animator.setDuration(CIRCLE_ANIM_DURATION_MS); 106d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague animator.setInterpolator(Gusterpolator.INSTANCE); 107d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 108d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague @Override 109d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague public void onAnimationUpdate(ValueAnimator animation) { 110d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague setLevel((Integer) animation.getAnimatedValue()); 111d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague } 112d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague }); 113d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague animator.start(); 114d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague } 115d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague 116d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague @Override 117d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague public void draw(Canvas canvas) { 118d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague mCanvasWidth = canvas.getWidth(); 119d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague mCanvasHeight = canvas.getHeight(); 120d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague 121d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague mRadius = map(getLevel(), 0, DRAWABLE_MAX_LEVEL, 122d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague 0, diagonalLength(canvas.getWidth(), canvas.getHeight())/2); 123d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague canvas.drawCircle(canvas.getWidth()/2.0f, canvas.getHeight()/2.0f, 124d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague mRadius, mPaint); 125d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague } 126d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague 127d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague /** 128d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague * Maps a given value x from one input range [in_min, in_max] to 129d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague * another output range [out_min, out-max]. 130d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague * @param x Value to be mapped. 131d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague * @param in_min Input range minimum. 132d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague * @param in_max Input range maximum. 133d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague * @param out_min Output range minimum. 134d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague * @param out_max Output range maximum. 135d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague * @return The mapped value. 136d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague */ 137d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague private static int map(int x, int in_min, int in_max, int out_min, int out_max) { 138d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; 139d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague } 140d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague 141d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague private static int diagonalLength(int w, int h) { 142d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague return (int) Math.sqrt((w*w) + (h*h)); 143d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague } 144d9516f276cd45f87edc7eafe6aa476eeab7c29e7Spike Sprague}