blob: ffad1122b22f2b7efe29e48e82a187af7139b197 [file] [log] [blame]
Doris Liu1dfe7822013-12-12 00:02:08 -08001/*
2 * Copyright (C) 2013 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
17package com.android.camera.ui;
18
19import android.animation.Animator;
20import android.animation.AnimatorSet;
21import android.animation.ValueAnimator;
22import android.content.Context;
23import android.graphics.Canvas;
24import android.graphics.Color;
25import android.graphics.Paint;
Doris Liua1ec04a2014-01-13 17:29:40 -080026import android.graphics.RectF;
Doris Liu1dfe7822013-12-12 00:02:08 -080027import android.util.AttributeSet;
28import android.view.View;
29
Angus Kong2bca2102014-03-11 16:27:30 -070030import com.android.camera.debug.Log;
Doris Liu1dfe7822013-12-12 00:02:08 -080031import com.android.camera.util.Gusterpolator;
32import com.android.camera2.R;
33
34/**
35 * This class handles all the animations at capture time. Post capture animations
36 * will be handled in a separate place.
37 */
Doris Liuca4a5662014-01-02 17:40:12 -080038public class CaptureAnimationOverlay extends View
Angus Kong2bacca72014-03-06 12:57:29 -080039 implements PreviewStatusListener.PreviewAreaChangedListener {
Angus Kong2bca2102014-03-11 16:27:30 -070040 private final static Log.Tag TAG = new Log.Tag("CaptureAnimOverlay");
Doris Liu1dfe7822013-12-12 00:02:08 -080041
Angus Kong9824f852014-02-10 14:54:29 -080042 private final static int FLASH_ANIMATION_DURATION_MS = 350;
Doris Liuce165802013-12-13 15:19:13 -080043 private final static int FLASH_CIRCLE_SHRINK_DURATION_MS = 200;
44 private final static int FLASH_CIRCLE_SLIDE_DURATION_MS = 400;
45 private final static int FLASH_CIRCLE_SLIDE_START_DELAY_MS = 0;
Doris Liu1dfe7822013-12-12 00:02:08 -080046 private final static int FLASH_ALPHA_BEFORE_SHRINK = 180;
47 private final static int FLASH_ALPHA_AFTER_SHRINK = 50;
48 private final static int FLASH_COLOR = Color.WHITE;
49
50 private int mWidth;
51 private int mHeight;
52 private int mFlashCircleCenterX;
53 private int mFlashCircleCenterY;
54 private int mFlashCircleRadius = 0;
Angus Kong9824f852014-02-10 14:54:29 -080055 private ValueAnimator mFlashAnimation;
56 private AnimatorSet mFlashCircleAnimation;
Doris Liu1dfe7822013-12-12 00:02:08 -080057 private final Paint mPaint = new Paint();
58 private final int mFlashCircleSizeAfterShrink;
59
60 public CaptureAnimationOverlay(Context context, AttributeSet attrs) {
61 super(context, attrs);
62 mPaint.setColor(FLASH_COLOR);
63 mFlashCircleSizeAfterShrink = getResources()
64 .getDimensionPixelSize(R.dimen.flash_circle_size_after_shrink);
65 }
66
Doris Liu1dfe7822013-12-12 00:02:08 -080067 /**
Angus Kong9824f852014-02-10 14:54:29 -080068 * Start flash circle animation with the circle of the flash being at
69 * position (x, y).
Doris Liuce165802013-12-13 15:19:13 -080070 *
Doris Liu1dfe7822013-12-12 00:02:08 -080071 * @param x position on x axis
72 * @param y position on y axis
73 */
Angus Kong9824f852014-02-10 14:54:29 -080074 public void startFlashCircleAnimation(int x, int y) {
75 if (mFlashCircleAnimation != null && mFlashCircleAnimation.isRunning()) {
76 mFlashCircleAnimation.cancel();
Doris Liu1dfe7822013-12-12 00:02:08 -080077 }
78
79 mFlashCircleCenterX = x;
80 mFlashCircleCenterY = y;
81
82 // Flash circle shrink.
83 final ValueAnimator alphaAnimator = ValueAnimator.ofInt(FLASH_ALPHA_BEFORE_SHRINK,
84 FLASH_ALPHA_AFTER_SHRINK);
85 alphaAnimator.setDuration(FLASH_CIRCLE_SHRINK_DURATION_MS);
Doris Liu1dfe7822013-12-12 00:02:08 -080086
87 int startingRadius = (int) Math.sqrt(mWidth * mWidth + mHeight * mHeight) / 2;
88 final ValueAnimator radiusAnimator = ValueAnimator.ofInt(startingRadius,
89 mFlashCircleSizeAfterShrink);
90 radiusAnimator.setDuration(FLASH_CIRCLE_SHRINK_DURATION_MS);
Doris Liu1dfe7822013-12-12 00:02:08 -080091 radiusAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
92 @Override
93 public void onAnimationUpdate(ValueAnimator animation) {
94 mFlashCircleRadius = (Integer) radiusAnimator.getAnimatedValue();
95 int alpha = (Integer) alphaAnimator.getAnimatedValue();
96 mPaint.setAlpha(alpha);
97 invalidate();
98 }
99 });
100
101 // Flash circle slide to the right edge of the screen.
102 int endPositionX = mWidth + mFlashCircleSizeAfterShrink;
103 final ValueAnimator slideAnimatorX = ValueAnimator.ofInt(mFlashCircleCenterX, endPositionX);
104 slideAnimatorX.setDuration(FLASH_CIRCLE_SLIDE_DURATION_MS);
105 slideAnimatorX.setStartDelay(FLASH_CIRCLE_SLIDE_START_DELAY_MS);
Doris Liu1dfe7822013-12-12 00:02:08 -0800106
107 final ValueAnimator slideAnimatorY = ValueAnimator.ofInt(y, mHeight / 2);
108 slideAnimatorY.setDuration(FLASH_CIRCLE_SLIDE_DURATION_MS);
109 slideAnimatorY.setStartDelay(FLASH_CIRCLE_SLIDE_START_DELAY_MS);
Doris Liu1dfe7822013-12-12 00:02:08 -0800110 slideAnimatorY.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
111 @Override
112 public void onAnimationUpdate(ValueAnimator animation) {
113 mFlashCircleCenterX = (Integer) slideAnimatorX.getAnimatedValue();
114 mFlashCircleCenterY = (Integer) slideAnimatorY.getAnimatedValue();
115 invalidate();
116 }
117 });
118
Angus Kong9824f852014-02-10 14:54:29 -0800119 mFlashCircleAnimation = new AnimatorSet();
120 mFlashCircleAnimation.play(alphaAnimator)
Doris Liu1dfe7822013-12-12 00:02:08 -0800121 .with(radiusAnimator)
122 .with(slideAnimatorX)
123 .with(slideAnimatorY);
Angus Kong9824f852014-02-10 14:54:29 -0800124 mFlashCircleAnimation.setInterpolator(Gusterpolator.INSTANCE);
125 mFlashCircleAnimation.addListener(new Animator.AnimatorListener() {
126 @Override
127 public void onAnimationStart(Animator animation) {
128 setVisibility(VISIBLE);
129 }
130
131 @Override
132 public void onAnimationEnd(Animator animation) {
133 mFlashCircleAnimation = null;
134 setVisibility(INVISIBLE);
135 }
136
137 @Override
138 public void onAnimationCancel(Animator animation) {
139
140 }
141
142 @Override
143 public void onAnimationRepeat(Animator animation) {
144
145 }
146 });
147 mFlashCircleAnimation.start();
148 }
149
150 /**
151 * Start flash circle animation in the center of the screen.
152 */
153 public void startFlashCircleAnimation() {
154 int x = mWidth / 2;
155 int y = mHeight / 2;
156 startFlashCircleAnimation(x, y);
157 }
158
159 /**
160 * Start flash animation.
161 */
162 public void startFlashAnimation() {
163 if (mFlashAnimation != null && mFlashAnimation.isRunning()) {
164 mFlashAnimation.cancel();
165 }
166
167 mFlashAnimation = ValueAnimator.ofFloat(0f, .5f, 0f);
168 mFlashAnimation.setDuration(FLASH_ANIMATION_DURATION_MS);
Doris Liuce165802013-12-13 15:19:13 -0800169 mFlashAnimation.setInterpolator(Gusterpolator.INSTANCE);
Angus Kong9824f852014-02-10 14:54:29 -0800170 mFlashAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
171 @Override
172 public void onAnimationUpdate(ValueAnimator animation) {
173 setAlpha((Float) animation.getAnimatedValue());
174 invalidate();
175 }
176 });
Doris Liu1dfe7822013-12-12 00:02:08 -0800177 mFlashAnimation.addListener(new Animator.AnimatorListener() {
178 @Override
179 public void onAnimationStart(Animator animation) {
180 setVisibility(VISIBLE);
181 }
182
183 @Override
184 public void onAnimationEnd(Animator animation) {
185 mFlashAnimation = null;
186 setVisibility(INVISIBLE);
187 }
188
189 @Override
190 public void onAnimationCancel(Animator animation) {
191
192 }
193
194 @Override
195 public void onAnimationRepeat(Animator animation) {
196
197 }
198 });
199 mFlashAnimation.start();
200 }
201
Doris Liu1dfe7822013-12-12 00:02:08 -0800202 @Override
203 public void onDraw(Canvas canvas) {
Angus Kong9824f852014-02-10 14:54:29 -0800204 if (mFlashCircleAnimation != null && mFlashCircleAnimation.isRunning()) {
Doris Liu1dfe7822013-12-12 00:02:08 -0800205 canvas.drawCircle(mFlashCircleCenterX, mFlashCircleCenterY, mFlashCircleRadius, mPaint);
206 }
Angus Kong9824f852014-02-10 14:54:29 -0800207 if (mFlashAnimation != null && mFlashAnimation.isRunning()) {
208 canvas.drawColor(Color.WHITE);
209 }
Doris Liu1dfe7822013-12-12 00:02:08 -0800210 }
Doris Liuca4a5662014-01-02 17:40:12 -0800211
212 @Override
Angus Kong2bacca72014-03-06 12:57:29 -0800213 public void onPreviewAreaChanged(RectF previewArea) {
Doris Liua1ec04a2014-01-13 17:29:40 -0800214 mWidth = (int) previewArea.width();
215 mHeight = (int) previewArea.height();
Doris Liuca4a5662014-01-02 17:40:12 -0800216 }
Doris Liu1dfe7822013-12-12 00:02:08 -0800217}