1 /* 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 17 package com.android.camera.ui; 18 19 import android.animation.Animator; 20 import android.animation.AnimatorSet; 21 import android.animation.ValueAnimator; 22 import android.content.Context; 23 import android.graphics.Canvas; 24 import android.graphics.Color; 25 import android.graphics.Paint; 26 import android.graphics.RectF; 27 import android.util.AttributeSet; 28 import android.view.View; 29 import android.view.animation.Interpolator; 30 import android.view.animation.LinearInterpolator; 31 32 import com.android.camera.debug.Log; 33 34 /** 35 * This class handles all the animations at capture time. Post capture animations 36 * will be handled in a separate place. 37 */ 38 public class CaptureAnimationOverlay extends View 39 implements PreviewStatusListener.PreviewAreaChangedListener { 40 private final static Log.Tag TAG = new Log.Tag("CaptureAnimOverlay"); 41 42 private final static int FLASH_COLOR = Color.WHITE; 43 44 private static final float FLASH_MAX_ALPHA = 0.85f; 45 private static final long FLASH_FULL_DURATION_MS = 65; 46 private static final long FLASH_DECREASE_DURATION_MS = 150; 47 private static final float SHORT_FLASH_MAX_ALPHA = 0.75f; 48 private static final long SHORT_FLASH_FULL_DURATION_MS = 34; 49 private static final long SHORT_FLASH_DECREASE_DURATION_MS = 100; 50 51 private AnimatorSet mFlashAnimation; 52 private final RectF mPreviewArea = new RectF(); 53 private final Paint mPaint = new Paint(); 54 private final Interpolator mFlashAnimInterpolator; 55 private final ValueAnimator.AnimatorUpdateListener mFlashAnimUpdateListener; 56 private final Animator.AnimatorListener mFlashAnimListener; 57 CaptureAnimationOverlay(Context context, AttributeSet attrs)58 public CaptureAnimationOverlay(Context context, AttributeSet attrs) { 59 super(context, attrs); 60 mPaint.setColor(FLASH_COLOR); 61 mFlashAnimInterpolator = new LinearInterpolator(); 62 mFlashAnimUpdateListener = new ValueAnimator.AnimatorUpdateListener() { 63 @Override 64 public void onAnimationUpdate(ValueAnimator animation) { 65 float alpha = 255.0f * (Float) animation.getAnimatedValue(); 66 mPaint.setAlpha((int) alpha); 67 invalidate(); 68 } 69 }; 70 mFlashAnimListener = new Animator.AnimatorListener() { 71 @Override 72 public void onAnimationStart(Animator animation) { 73 setVisibility(VISIBLE); 74 } 75 76 @Override 77 public void onAnimationEnd(Animator animation) { 78 mFlashAnimation = null; 79 setVisibility(INVISIBLE); 80 } 81 82 @Override 83 public void onAnimationCancel(Animator animation) { 84 // End is always called after cancel. 85 } 86 87 @Override 88 public void onAnimationRepeat(Animator animation) { 89 90 } 91 }; 92 } 93 94 /** 95 * Start flash animation. 96 * 97 * @param shortFlash show shortest possible flash instead of regular long version. 98 */ startFlashAnimation(boolean shortFlash)99 public void startFlashAnimation(boolean shortFlash) { 100 if (mFlashAnimation != null && mFlashAnimation.isRunning()) { 101 mFlashAnimation.cancel(); 102 } 103 float maxAlpha; 104 105 if (shortFlash) { 106 maxAlpha = SHORT_FLASH_MAX_ALPHA; 107 } else { 108 maxAlpha = FLASH_MAX_ALPHA; 109 } 110 111 ValueAnimator flashAnim1 = ValueAnimator.ofFloat(maxAlpha, maxAlpha); 112 ValueAnimator flashAnim2 = ValueAnimator.ofFloat(maxAlpha, .0f); 113 114 if (shortFlash) { 115 flashAnim1.setDuration(SHORT_FLASH_FULL_DURATION_MS); 116 flashAnim2.setDuration(SHORT_FLASH_DECREASE_DURATION_MS); 117 } else { 118 flashAnim1.setDuration(FLASH_FULL_DURATION_MS); 119 flashAnim2.setDuration(FLASH_DECREASE_DURATION_MS); 120 } 121 122 flashAnim1.addUpdateListener(mFlashAnimUpdateListener); 123 flashAnim2.addUpdateListener(mFlashAnimUpdateListener); 124 flashAnim1.setInterpolator(mFlashAnimInterpolator); 125 flashAnim2.setInterpolator(mFlashAnimInterpolator); 126 127 mFlashAnimation = new AnimatorSet(); 128 mFlashAnimation.play(flashAnim1).before(flashAnim2); 129 mFlashAnimation.addListener(mFlashAnimListener); 130 mFlashAnimation.start(); 131 } 132 133 @Override onPreviewAreaChanged(RectF previewArea)134 public void onPreviewAreaChanged(RectF previewArea) { 135 mPreviewArea.set(previewArea); 136 } 137 138 @Override onDraw(Canvas canvas)139 public void onDraw(Canvas canvas) { 140 if (mFlashAnimation != null && mFlashAnimation.isRunning()) { 141 // mPaint alpha is animated by the animation. 142 canvas.drawRect(mPreviewArea, mPaint); 143 canvas.clipRect(mPreviewArea); 144 } 145 } 146 147 @Override hasOverlappingRendering()148 public boolean hasOverlappingRendering() { 149 // The internal draw method will NOT have draw calls that overlap. 150 return false; 151 } 152 } 153