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; 18 19 import android.animation.Animator; 20 import android.animation.AnimatorSet; 21 import android.animation.ObjectAnimator; 22 import android.view.View; 23 24 /** 25 * Class to handle animations. 26 */ 27 28 public class AnimationManager { 29 30 public static final float FLASH_ALPHA_START = 0.3f; 31 public static final float FLASH_ALPHA_END = 0f; 32 public static final int FLASH_DURATION = 300; 33 34 public static final int SHRINK_DURATION = 400; 35 public static final int HOLD_DURATION = 2500; 36 public static final int SLIDE_DURATION = 1100; 37 38 private ObjectAnimator mFlashAnim; 39 private AnimatorSet mCaptureAnimator; 40 41 /** 42 * Starts capture animation. 43 * @param view a thumbnail view that shows a picture captured and gets animated 44 */ startCaptureAnimation(final View view)45 public void startCaptureAnimation(final View view) { 46 if (mCaptureAnimator != null && mCaptureAnimator.isStarted()) { 47 mCaptureAnimator.cancel(); 48 } 49 View parentView = (View) view.getParent(); 50 float slideDistance = (float) (parentView.getWidth() - view.getLeft()); 51 52 float scaleX = ((float) parentView.getWidth()) / ((float) view.getWidth()); 53 float scaleY = ((float) parentView.getHeight()) / ((float) view.getHeight()); 54 float scale = scaleX > scaleY ? scaleX : scaleY; 55 56 int centerX = view.getLeft() + view.getWidth() / 2; 57 int centerY = view.getTop() + view.getHeight() / 2; 58 59 ObjectAnimator slide = ObjectAnimator.ofFloat(view, "translationX", 0f, slideDistance) 60 .setDuration(AnimationManager.SLIDE_DURATION); 61 slide.setStartDelay(AnimationManager.SHRINK_DURATION + AnimationManager.HOLD_DURATION); 62 63 ObjectAnimator translateY = ObjectAnimator.ofFloat(view, "translationY", 64 parentView.getHeight() / 2 - centerY, 0f) 65 .setDuration(AnimationManager.SHRINK_DURATION); 66 translateY.addListener(new Animator.AnimatorListener() { 67 @Override 68 public void onAnimationStart(Animator animator) { 69 // Do nothing. 70 } 71 72 @Override 73 public void onAnimationEnd(Animator animator) { 74 view.setClickable(true); 75 } 76 77 @Override 78 public void onAnimationCancel(Animator animator) { 79 // Do nothing. 80 } 81 82 @Override 83 public void onAnimationRepeat(Animator animator) { 84 // Do nothing. 85 } 86 }); 87 88 mCaptureAnimator = new AnimatorSet(); 89 mCaptureAnimator.playTogether( 90 ObjectAnimator.ofFloat(view, "scaleX", scale, 1f) 91 .setDuration(AnimationManager.SHRINK_DURATION), 92 ObjectAnimator.ofFloat(view, "scaleY", scale, 1f) 93 .setDuration(AnimationManager.SHRINK_DURATION), 94 ObjectAnimator.ofFloat(view, "translationX", 95 parentView.getWidth() / 2 - centerX, 0f) 96 .setDuration(AnimationManager.SHRINK_DURATION), 97 translateY, 98 slide); 99 mCaptureAnimator.addListener(new Animator.AnimatorListener() { 100 @Override 101 public void onAnimationStart(Animator animator) { 102 view.setClickable(false); 103 view.setVisibility(View.VISIBLE); 104 } 105 106 @Override 107 public void onAnimationEnd(Animator animator) { 108 view.setScaleX(1f); 109 view.setScaleX(1f); 110 view.setTranslationX(0f); 111 view.setTranslationY(0f); 112 view.setVisibility(View.INVISIBLE); 113 mCaptureAnimator.removeAllListeners(); 114 mCaptureAnimator = null; 115 } 116 117 @Override 118 public void onAnimationCancel(Animator animator) { 119 view.setVisibility(View.INVISIBLE); 120 } 121 122 @Override 123 public void onAnimationRepeat(Animator animator) { 124 // Do nothing. 125 } 126 }); 127 mCaptureAnimator.start(); 128 } 129 130 /** 131 * Starts flash animation. 132 * @params flashOverlay the overlay that will animate on alpha to make the flash impression 133 */ startFlashAnimation(final View flashOverlay)134 public void startFlashAnimation(final View flashOverlay) { 135 // End the previous animation if the previous one is still running 136 if (mFlashAnim != null && mFlashAnim.isRunning()) { 137 mFlashAnim.cancel(); 138 } 139 // Start new flash animation. 140 mFlashAnim = ObjectAnimator.ofFloat(flashOverlay, "alpha", 141 AnimationManager.FLASH_ALPHA_START, AnimationManager.FLASH_ALPHA_END); 142 mFlashAnim.setDuration(AnimationManager.FLASH_DURATION); 143 mFlashAnim.addListener(new Animator.AnimatorListener() { 144 @Override 145 public void onAnimationStart(Animator animator) { 146 flashOverlay.setVisibility(View.VISIBLE); 147 } 148 149 @Override 150 public void onAnimationEnd(Animator animator) { 151 flashOverlay.setAlpha(0f); 152 flashOverlay.setVisibility(View.GONE); 153 mFlashAnim.removeAllListeners(); 154 mFlashAnim = null; 155 } 156 157 @Override 158 public void onAnimationCancel(Animator animator) { 159 // Do nothing. 160 } 161 162 @Override 163 public void onAnimationRepeat(Animator animator) { 164 // Do nothing. 165 } 166 }); 167 mFlashAnim.start(); 168 } 169 170 /** 171 * Cancels on-going flash animation and capture animation, if any. 172 */ cancelAnimations()173 public void cancelAnimations() { 174 // End the previous animation if the previous one is still running 175 if (mFlashAnim != null && mFlashAnim.isRunning()) { 176 mFlashAnim.cancel(); 177 } 178 if (mCaptureAnimator != null && mCaptureAnimator.isStarted()) { 179 mCaptureAnimator.cancel(); 180 } 181 } 182 } 183