CaptureAnimManager.java revision 3a5b0163009c43a2e2969568baa5fe0efbaf07f5
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 float mXDelta; 48 private float mYDelta; 49 private float mXDeltaScaled; 50 private 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 */ 64 public CaptureAnimManager(View preview, ImageView review) { 65 mReview = review; 66 mPreview = preview; 67 68 mCaptureAnim.setInterpolator(new AccelerateDecelerateInterpolator()); 69 mCaptureAnim.setDuration(CAPTURE_ANIM_DURATION); 70 mCaptureAnim.addListener(this); 71 mCaptureAnim.addUpdateListener(this); 72 } 73 74 void initializeDelta(int xDelta, int yDelta) { 75 mXDelta = xDelta; 76 mYDelta = yDelta; 77 mXDeltaScaled = mXDelta * TOTAL_RATIO; 78 mYDeltaScaled = mYDelta * TOTAL_RATIO; 79 mReviewSlideValue[0] = PropertyValuesHolder.ofFloat("", 0f, mXDeltaScaled); 80 mReviewSlideValue[1] = PropertyValuesHolder.ofFloat("", 0f, -mYDeltaScaled); 81 mReviewSlideValue[2] = PropertyValuesHolder.ofFloat("", 0f, -mXDeltaScaled); 82 mReviewSlideValue[3] = PropertyValuesHolder.ofFloat("", 0f, mYDeltaScaled); 83 } 84 85 // xDelta, yDelta: The dimension of the viewfinder in which animation happens. 86 public void startAnimation(Bitmap bitmap, int animOrientation, int xDelta, int yDelta) { 87 if (xDelta != mXDelta || mYDelta != yDelta) { 88 initializeDelta(xDelta, yDelta); 89 } 90 mAnimOrientation = animOrientation; 91 // Reset the views before the animation begins. 92 mCaptureAnim.cancel(); 93 mCaptureAnim.setValues(mReviewSlideValue[(mAnimOrientation / 90) % 4]); 94 switch (mAnimOrientation) { 95 case 0: 96 mPreview.setTranslationX(-mXDeltaScaled); 97 mPreview.setPivotX(mXDelta * (1f + VIEW_GAP_RATIO / 2f)); //left 98 mReview.setPivotX(mXDelta * -VIEW_GAP_RATIO / 2f); //right 99 mPreview.setPivotY(mYDeltaScaled / 2f); 100 mReview.setPivotY(mYDeltaScaled / 2f); 101 mOffset = -mXDeltaScaled; 102 break; 103 case 90: 104 mPreview.setTranslationY(mYDeltaScaled); 105 mPreview.setPivotX(mXDeltaScaled / 2f); 106 mReview.setPivotX(mXDeltaScaled / 2f); 107 mPreview.setPivotY(mYDelta * -VIEW_GAP_RATIO / 2f); //down 108 mReview.setPivotY(mYDelta * (1f + VIEW_GAP_RATIO / 2f)); //up 109 mOffset = (mYDeltaScaled); 110 break; 111 case 180: 112 mPreview.setTranslationX(mXDeltaScaled); 113 mPreview.setPivotX(mXDelta * -VIEW_GAP_RATIO / 2f); //right 114 mReview.setPivotX(mXDelta * (1f + VIEW_GAP_RATIO / 2f)); //left 115 mPreview.setPivotY(mYDeltaScaled / 2f); 116 mReview.setPivotY(mYDeltaScaled / 2f); 117 mOffset = mXDeltaScaled; 118 break; 119 case 270: 120 mPreview.setTranslationY(-mYDeltaScaled); 121 mPreview.setPivotX(mXDeltaScaled / 2f); 122 mReview.setPivotX(mXDeltaScaled / 2f); 123 mPreview.setPivotY(mYDelta * (1f + VIEW_GAP_RATIO / 2f)); //up 124 mReview.setPivotY(mYDelta * -VIEW_GAP_RATIO / 2f); //down 125 mOffset = -mYDeltaScaled; 126 break; 127 } 128 129 mReview.setImageBitmap(bitmap); 130 mReview.setTranslationX(0f); 131 mReview.setTranslationY(0f); 132 mReview.setScaleX(1f); 133 mReview.setScaleY(1f); 134 mReview.setVisibility(View.VISIBLE); 135 mCaptureAnim.start(); 136 } 137 138 @Override 139 public void onAnimationStart(Animator anim) { 140 } 141 142 @Override 143 public void onAnimationEnd(Animator anim) { 144 mReview.setVisibility(View.GONE); 145 mReview.setImageBitmap(null); 146 } 147 148 @Override 149 public void onAnimationRepeat(Animator anim) {} 150 151 @Override 152 public void onAnimationCancel(Animator anim) {} 153 154 @Override 155 public void onAnimationUpdate(ValueAnimator anim) { 156 float fraction = anim.getAnimatedFraction(); 157 zoomAnimation(fraction); 158 mPreview.setAlpha(fraction); 159 slideAnimation((Float) anim.getAnimatedValue()); 160 } 161 162 // Take a translation value of the review and calculate the corresponding value for 163 // the preview. 164 private void slideAnimation(float value) { 165 if (mAnimOrientation == 0 || mAnimOrientation == 180) { 166 // Slide horizontally. 167 mReview.setTranslationX(value); 168 mPreview.setTranslationX(value + mOffset); 169 } else { 170 // Slide vertically. 171 mReview.setTranslationY(value); 172 mPreview.setTranslationY(value + mOffset); 173 } 174 } 175 176 // Calculate the zoom factor based on the given time fraction. 177 private void zoomAnimation(float fraction) { 178 float value = 1f; 179 if (fraction <= 0.5f) { 180 // Zoom in for the beginning. 181 value = 1f - ZOOM_DELTA * ZoomOutInterpolator.getInterpolation( 182 fraction * 2); 183 } else { 184 // Zoom out for the last. 185 value = ZOOM_IN_BEGIN + ZOOM_DELTA * ZoomInInterpolator.getInterpolation( 186 (fraction - 0.5f) * 2f); 187 } 188 mReview.setScaleX(value); 189 mReview.setScaleY(value); 190 mPreview.setScaleX(value); 191 mPreview.setScaleY(value); 192 } 193} 194