CaptureAnimManager.java revision 6fc7917e8636118a3a1bbfe6411ed5f11b974cf1
1/* 2 * Copyright (C) 2012 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; 18 19import android.animation.Animator; 20import android.animation.PropertyValuesHolder; 21import android.animation.ValueAnimator; 22import android.graphics.Bitmap; 23import android.view.View; 24import android.view.animation.AccelerateDecelerateInterpolator; 25import android.view.animation.AccelerateInterpolator; 26import android.view.animation.DecelerateInterpolator; 27import android.view.animation.Interpolator; 28import android.widget.ImageView; 29 30/** 31 * Class to handle the capture animation. 32 */ 33public class CaptureAnimManager implements 34 ValueAnimator.AnimatorUpdateListener, Animator.AnimatorListener { 35 36 private static final float ZOOM_DELTA = 0.2f; // The amount of change for zooming out. 37 private static final float ZOOM_IN_BEGIN = 1f - ZOOM_DELTA; // Pre-calculated value for 38 // convenience. 39 private static final long CAPTURE_ANIM_DURATION = 800; // milliseconds. 40 private static final float VIEW_GAP_RATIO = 0.1f; // The gap between preview and review based 41 // on the view dimension. 42 private static final float TOTAL_RATIO = 1f + VIEW_GAP_RATIO; 43 44 private final ImageView mReview; 45 private final View mPreview; 46 47 private final float mXDelta; 48 private final float mYDelta; 49 private final float mXDeltaScaled; 50 private final float mYDeltaScaled; 51 private float mOffset; // The offset where preview should be put relative to the review. 52 private int mAnimOrientation; 53 54 private final Interpolator ZoomOutInterpolator = new DecelerateInterpolator(); 55 private final Interpolator ZoomInInterpolator = new AccelerateInterpolator(); 56 57 private final ValueAnimator mCaptureAnim = new ValueAnimator(); 58 // The translation value for 4 different orientations. 59 private final PropertyValuesHolder[] mReviewSlideValue = new PropertyValuesHolder[4]; 60 61 /* preview: camera preview view. 62 * review: view of picture just taken. 63 * xDelta, yDelta: The dimension of the viewfinder in which animation happens. 64 */ 65 public CaptureAnimManager(View preview, ImageView review, int xDelta, int yDelta) { 66 mReview = review; 67 mPreview = preview; 68 69 mCaptureAnim.setInterpolator(new AccelerateDecelerateInterpolator()); 70 mCaptureAnim.setDuration(CAPTURE_ANIM_DURATION); 71 mCaptureAnim.addListener(this); 72 mCaptureAnim.addUpdateListener(this); 73 74 mXDelta = xDelta; 75 mYDelta = yDelta; 76 mXDeltaScaled = mXDelta * TOTAL_RATIO; 77 mYDeltaScaled = mYDelta * TOTAL_RATIO; 78 mReviewSlideValue[0] = PropertyValuesHolder.ofFloat("", 0f, mXDeltaScaled); 79 mReviewSlideValue[1] = PropertyValuesHolder.ofFloat("", 0f, -mYDeltaScaled); 80 mReviewSlideValue[2] = PropertyValuesHolder.ofFloat("", 0f, -mXDeltaScaled); 81 mReviewSlideValue[3] = PropertyValuesHolder.ofFloat("", 0f, mYDeltaScaled); 82 } 83 84 public void startAnimation(Bitmap bitmap, int animOrientation) { 85 mAnimOrientation = animOrientation; 86 // Reset the views before the animation begins. 87 mCaptureAnim.cancel(); 88 mCaptureAnim.setValues(mReviewSlideValue[(mAnimOrientation / 90) % 4]); 89 switch (mAnimOrientation) { 90 case 0: 91 mPreview.setTranslationX(-mXDeltaScaled); 92 mPreview.setPivotX(mXDelta * (1f + VIEW_GAP_RATIO / 2f)); //left 93 mReview.setPivotX(mXDelta * -VIEW_GAP_RATIO / 2f); //right 94 mPreview.setPivotY(mYDeltaScaled / 2f); 95 mReview.setPivotY(mYDeltaScaled / 2f); 96 mOffset = -mXDeltaScaled; 97 break; 98 case 90: 99 mPreview.setTranslationY(mYDeltaScaled); 100 mPreview.setPivotX(mXDeltaScaled / 2f); 101 mReview.setPivotX(mXDeltaScaled / 2f); 102 mPreview.setPivotY(mYDelta * -VIEW_GAP_RATIO / 2f); //down 103 mReview.setPivotY(mYDelta * (1f + VIEW_GAP_RATIO / 2f)); //up 104 mOffset = (mYDeltaScaled); 105 break; 106 case 180: 107 mPreview.setTranslationX(mXDeltaScaled); 108 mPreview.setPivotX(mXDelta * -VIEW_GAP_RATIO / 2f); //right 109 mReview.setPivotX(mXDelta * (1f + VIEW_GAP_RATIO / 2f)); //left 110 mPreview.setPivotY(mYDeltaScaled / 2f); 111 mReview.setPivotY(mYDeltaScaled / 2f); 112 mOffset = mXDeltaScaled; 113 break; 114 case 270: 115 mPreview.setTranslationY(-mYDeltaScaled); 116 mPreview.setPivotX(mXDeltaScaled / 2f); 117 mReview.setPivotX(mXDeltaScaled / 2f); 118 mPreview.setPivotY(mYDelta * (1f + VIEW_GAP_RATIO / 2f)); //up 119 mReview.setPivotY(mYDelta * -VIEW_GAP_RATIO / 2f); //down 120 mOffset = -mYDeltaScaled; 121 break; 122 } 123 124 mReview.setImageBitmap(bitmap); 125 mReview.setTranslationX(0f); 126 mReview.setTranslationY(0f); 127 mReview.setScaleX(1f); 128 mReview.setScaleY(1f); 129 mReview.setVisibility(View.VISIBLE); 130 mCaptureAnim.start(); 131 } 132 133 @Override 134 public void onAnimationStart(Animator anim) { 135 } 136 137 @Override 138 public void onAnimationEnd(Animator anim) { 139 mReview.setVisibility(View.GONE); 140 mReview.setImageBitmap(null); 141 } 142 143 @Override 144 public void onAnimationRepeat(Animator anim) {} 145 146 @Override 147 public void onAnimationCancel(Animator anim) {} 148 149 @Override 150 public void onAnimationUpdate(ValueAnimator anim) { 151 float fraction = anim.getAnimatedFraction(); 152 zoomAnimation(fraction); 153 mPreview.setAlpha(fraction); 154 slideAnimation((Float) anim.getAnimatedValue()); 155 } 156 157 // Take a translation value of the review and calculate the corresponding value for 158 // the preview. 159 private void slideAnimation(float value) { 160 if (mAnimOrientation == 0 || mAnimOrientation == 180) { 161 // Slide horizontally. 162 mReview.setTranslationX(value); 163 mPreview.setTranslationX(value + mOffset); 164 } else { 165 // Slide vertically. 166 mReview.setTranslationY(value); 167 mPreview.setTranslationY(value + mOffset); 168 } 169 } 170 171 // Calculate the zoom factor based on the given time fraction. 172 private void zoomAnimation(float fraction) { 173 float value = 1f; 174 if (fraction <= 0.5f) { 175 // Zoom in for the beginning. 176 value = 1f - ZOOM_DELTA * ZoomOutInterpolator.getInterpolation( 177 fraction * 2); 178 } else { 179 // Zoom out for the last. 180 value = ZOOM_IN_BEGIN + ZOOM_DELTA * ZoomInInterpolator.getInterpolation( 181 (fraction - 0.5f) * 2f); 182 } 183 mReview.setScaleX(value); 184 mReview.setScaleY(value); 185 mPreview.setScaleX(value); 186 mPreview.setScaleY(value); 187 } 188} 189