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