summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteve Kondik <steve@cyngn.com>2016-11-09 01:17:49 -0800
committerSteve Kondik <steve@cyngn.com>2016-11-13 23:33:36 -0800
commitf886863e6d8024ef6d2c2712aa518a761fff6b9d (patch)
tree48e17f4ab5372589629da48779caa04cb66fca8a
parent4538ee80f8a9eb338281db00fb349e111eeb5aaf (diff)
downloadandroid_packages_apps_Snap-f886863e6d8024ef6d2c2712aa518a761fff6b9d.zip
android_packages_apps_Snap-f886863e6d8024ef6d2c2712aa518a761fff6b9d.tar.gz
android_packages_apps_Snap-f886863e6d8024ef6d2c2712aa518a761fff6b9d.tar.bz2
snap: Better capture animation
* Modified version from Camera2 * Also adjust the callbacks for better response Change-Id: I85ac23cdf35d9e2625799dd64b9f86aef103be7b
-rw-r--r--res/layout/capture_module.xml9
-rw-r--r--res/layout/photo_module.xml12
-rw-r--r--res/layout/video_module.xml12
-rw-r--r--src/com/android/camera/AnimationManager.java182
-rw-r--r--src/com/android/camera/BaseUI.java14
-rw-r--r--src/com/android/camera/CaptureUI.java4
-rw-r--r--src/com/android/camera/PhotoModule.java13
-rw-r--r--src/com/android/camera/PhotoUI.java10
-rw-r--r--src/com/android/camera/VideoModule.java7
-rw-r--r--src/com/android/camera/VideoUI.java44
-rw-r--r--src/com/android/camera/ui/CaptureAnimationOverlay.java148
11 files changed, 203 insertions, 252 deletions
diff --git a/res/layout/capture_module.xml b/res/layout/capture_module.xml
index b03c433..dba8de9 100644
--- a/res/layout/capture_module.xml
+++ b/res/layout/capture_module.xml
@@ -64,7 +64,14 @@
android:id="@+id/focus_ring"
android:layout_width="match_parent"
android:layout_height="match_parent" />
- </FrameLayout>
+
+ <com.android.camera.ui.CaptureAnimationOverlay
+ android:id="@+id/capture_overlay"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:visibility="gone" />
+
+ </FrameLayout>
<com.android.camera.ui.RenderOverlay
android:id="@+id/render_overlay"
diff --git a/res/layout/photo_module.xml b/res/layout/photo_module.xml
index f184e0c..794a968 100644
--- a/res/layout/photo_module.xml
+++ b/res/layout/photo_module.xml
@@ -45,6 +45,11 @@
android:id="@+id/focus_ring"
android:layout_width="match_parent"
android:layout_height="match_parent" />
+ <com.android.camera.ui.CaptureAnimationOverlay
+ android:id="@+id/capture_overlay"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:visibility="gone" />
<com.android.camera.ui.RotateImageView
android:id="@+id/review_image"
android:layout_width="match_parent"
@@ -53,13 +58,6 @@
android:clickable="true"
android:background="@android:color/black"
android:scaleType="fitCenter"/>
- <View
- android:id="@+id/flash_overlay"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:background="@android:color/white"
- android:visibility="gone"
- android:alpha="0" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
diff --git a/res/layout/video_module.xml b/res/layout/video_module.xml
index c6a9d7e..f12f06c 100644
--- a/res/layout/video_module.xml
+++ b/res/layout/video_module.xml
@@ -43,13 +43,6 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/black" />
- <View
- android:id="@+id/flash_overlay"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:background="@android:color/white"
- android:visibility="gone"
- android:alpha="0" />
<FrameLayout android:id="@+id/preview_border"
android:layout_width="match_parent"
android:layout_height="match_parent"
@@ -81,6 +74,11 @@
android:id="@+id/focus_ring"
android:layout_width="match_parent"
android:layout_height="match_parent" />
+ <com.android.camera.ui.CaptureAnimationOverlay
+ android:id="@+id/capture_overlay"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:visibility="gone" />
<ImageView android:id="@+id/review_image"
android:layout_height="match_parent"
android:layout_width="match_parent"
diff --git a/src/com/android/camera/AnimationManager.java b/src/com/android/camera/AnimationManager.java
deleted file mode 100644
index 5397ae0..0000000
--- a/src/com/android/camera/AnimationManager.java
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.camera;
-
-import android.animation.Animator;
-import android.animation.AnimatorSet;
-import android.animation.ObjectAnimator;
-import android.view.View;
-
-/**
- * Class to handle animations.
- */
-
-public class AnimationManager {
-
- public static final float FLASH_ALPHA_START = 0.3f;
- public static final float FLASH_ALPHA_END = 0f;
- public static final int FLASH_DURATION = 300;
-
- public static final int SHRINK_DURATION = 400;
- public static final int HOLD_DURATION = 2500;
- public static final int SLIDE_DURATION = 1100;
-
- private ObjectAnimator mFlashAnim;
- private AnimatorSet mCaptureAnimator;
-
- /**
- * Starts capture animation.
- * @param view a thumbnail view that shows a picture captured and gets animated
- */
- public void startCaptureAnimation(final View view) {
- if (mCaptureAnimator != null && mCaptureAnimator.isStarted()) {
- mCaptureAnimator.cancel();
- }
- View parentView = (View) view.getParent();
- float slideDistance = (float) (parentView.getWidth() - view.getLeft());
-
- float scaleX = ((float) parentView.getWidth()) / ((float) view.getWidth());
- float scaleY = ((float) parentView.getHeight()) / ((float) view.getHeight());
- float scale = scaleX > scaleY ? scaleX : scaleY;
-
- int centerX = view.getLeft() + view.getWidth() / 2;
- int centerY = view.getTop() + view.getHeight() / 2;
-
- ObjectAnimator slide = ObjectAnimator.ofFloat(view, "translationX", 0f, slideDistance)
- .setDuration(AnimationManager.SLIDE_DURATION);
- slide.setStartDelay(AnimationManager.SHRINK_DURATION + AnimationManager.HOLD_DURATION);
-
- ObjectAnimator translateY = ObjectAnimator.ofFloat(view, "translationY",
- parentView.getHeight() / 2 - centerY, 0f)
- .setDuration(AnimationManager.SHRINK_DURATION);
- translateY.addListener(new Animator.AnimatorListener() {
- @Override
- public void onAnimationStart(Animator animator) {
- // Do nothing.
- }
-
- @Override
- public void onAnimationEnd(Animator animator) {
- view.setClickable(true);
- }
-
- @Override
- public void onAnimationCancel(Animator animator) {
- // Do nothing.
- }
-
- @Override
- public void onAnimationRepeat(Animator animator) {
- // Do nothing.
- }
- });
-
- mCaptureAnimator = new AnimatorSet();
- mCaptureAnimator.playTogether(
- ObjectAnimator.ofFloat(view, "scaleX", scale, 1f)
- .setDuration(AnimationManager.SHRINK_DURATION),
- ObjectAnimator.ofFloat(view, "scaleY", scale, 1f)
- .setDuration(AnimationManager.SHRINK_DURATION),
- ObjectAnimator.ofFloat(view, "translationX",
- parentView.getWidth() / 2 - centerX, 0f)
- .setDuration(AnimationManager.SHRINK_DURATION),
- translateY,
- slide);
- mCaptureAnimator.addListener(new Animator.AnimatorListener() {
- @Override
- public void onAnimationStart(Animator animator) {
- view.setClickable(false);
- view.setVisibility(View.VISIBLE);
- }
-
- @Override
- public void onAnimationEnd(Animator animator) {
- view.setScaleX(1f);
- view.setScaleX(1f);
- view.setTranslationX(0f);
- view.setTranslationY(0f);
- view.setVisibility(View.INVISIBLE);
- mCaptureAnimator.removeAllListeners();
- mCaptureAnimator = null;
- }
-
- @Override
- public void onAnimationCancel(Animator animator) {
- view.setVisibility(View.INVISIBLE);
- }
-
- @Override
- public void onAnimationRepeat(Animator animator) {
- // Do nothing.
- }
- });
- mCaptureAnimator.start();
- }
-
- /**
- * Starts flash animation.
- * @params flashOverlay the overlay that will animate on alpha to make the flash impression
- */
- public void startFlashAnimation(final View flashOverlay) {
- // End the previous animation if the previous one is still running
- if (mFlashAnim != null && mFlashAnim.isRunning()) {
- mFlashAnim.cancel();
- }
- // Start new flash animation.
- mFlashAnim = ObjectAnimator.ofFloat(flashOverlay, "alpha",
- AnimationManager.FLASH_ALPHA_START, AnimationManager.FLASH_ALPHA_END);
- mFlashAnim.setDuration(AnimationManager.FLASH_DURATION);
- mFlashAnim.addListener(new Animator.AnimatorListener() {
- @Override
- public void onAnimationStart(Animator animator) {
- flashOverlay.setVisibility(View.VISIBLE);
- }
-
- @Override
- public void onAnimationEnd(Animator animator) {
- flashOverlay.setAlpha(0f);
- flashOverlay.setVisibility(View.GONE);
- mFlashAnim.removeAllListeners();
- mFlashAnim = null;
- }
-
- @Override
- public void onAnimationCancel(Animator animator) {
- // Do nothing.
- }
-
- @Override
- public void onAnimationRepeat(Animator animator) {
- // Do nothing.
- }
- });
- mFlashAnim.start();
- }
-
- /**
- * Cancels on-going flash animation and capture animation, if any.
- */
- public void cancelAnimations() {
- // End the previous animation if the previous one is still running
- if (mFlashAnim != null && mFlashAnim.isRunning()) {
- mFlashAnim.cancel();
- }
- if (mCaptureAnimator != null && mCaptureAnimator.isStarted()) {
- mCaptureAnimator.cancel();
- }
- }
-}
diff --git a/src/com/android/camera/BaseUI.java b/src/com/android/camera/BaseUI.java
index 3721062..f48b287 100644
--- a/src/com/android/camera/BaseUI.java
+++ b/src/com/android/camera/BaseUI.java
@@ -1,10 +1,12 @@
package com.android.camera;
import android.graphics.Point;
+import android.graphics.RectF;
import android.view.View;
import android.view.ViewGroup;
import com.android.camera.ui.CameraControls;
+import com.android.camera.ui.CaptureAnimationOverlay;
import com.android.camera.ui.ModuleSwitcher;
import com.android.camera.util.CameraUtil;
@@ -15,6 +17,7 @@ import org.codeaurora.snapcam.R;
public abstract class BaseUI {
protected final CameraControls mCameraControls;
+ protected final CaptureAnimationOverlay mCaptureOverlay;
protected final View mPreviewCover;
protected final CameraActivity mActivity;
@@ -31,6 +34,7 @@ public abstract class BaseUI {
mActivity.getLayoutInflater().inflate(layout, mRootView, true);
mCameraControls = (CameraControls) mRootView.findViewById(R.id.camera_controls);
+ mCaptureOverlay = (CaptureAnimationOverlay) mRootView.findViewById(R.id.capture_overlay);
mPreviewCover = mRootView.findViewById(R.id.preview_cover);
Point size = new Point();
@@ -119,4 +123,14 @@ public abstract class BaseUI {
}
mCameraControls.setModuleIndex(module);
}
+
+ public void animateFlash(boolean shortFlash) {
+ if (mCaptureOverlay != null) {
+ mCaptureOverlay.startFlashAnimation(shortFlash);
+ }
+ }
+
+ protected void onPreviewRectChanged(RectF rect) {
+ mCaptureOverlay.setPreviewRect(rect);
+ }
}
diff --git a/src/com/android/camera/CaptureUI.java b/src/com/android/camera/CaptureUI.java
index afebab7..81aa2b0 100644
--- a/src/com/android/camera/CaptureUI.java
+++ b/src/com/android/camera/CaptureUI.java
@@ -25,6 +25,7 @@ import android.content.res.Resources;
import android.graphics.ImageFormat;
import android.graphics.Point;
import android.graphics.Rect;
+import android.graphics.RectF;
import android.graphics.drawable.AnimationDrawable;
import android.hardware.Camera.Face;
import android.media.ImageReader;
@@ -182,6 +183,9 @@ public class CaptureUI extends BaseUI implements PreviewGestures.SingleTapListen
// SurfaceHolder callbacks
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
+ RectF r = new RectF(mSurfaceView.getLeft(), mSurfaceView.getTop(),
+ mSurfaceView.getRight(), mSurfaceView.getBottom());
+ CaptureUI.this.onPreviewRectChanged(r);
Log.v(TAG, "surfaceChanged: width =" + width + ", height = " + height);
}
diff --git a/src/com/android/camera/PhotoModule.java b/src/com/android/camera/PhotoModule.java
index d6f23e3..8085c40 100644
--- a/src/com/android/camera/PhotoModule.java
+++ b/src/com/android/camera/PhotoModule.java
@@ -1656,7 +1656,7 @@ public class PhotoModule
// i.e. If monkey/a user swipes to the gallery during picture taking,
// don't show animation
if (!mIsImageCaptureIntent) {
- mUI.animateFlash();
+ mUI.animateFlash(mFocusManager.isZslEnabled());
}
}
@@ -1674,7 +1674,9 @@ public class PhotoModule
mPostViewPictureCallbackTime = 0;
mJpegImageData = null;
- final boolean animateBefore = (mSceneMode == CameraUtil.SCENE_MODE_HDR);
+ final boolean animateBefore = (mSceneMode == CameraUtil.SCENE_MODE_HDR) ||
+ (mSnapshotMode == CameraInfo.CAMERA_SUPPORT_MODE_ZSL);
+
if(mHistogramEnabled) {
if (mSnapshotMode != CameraInfo.CAMERA_SUPPORT_MODE_ZSL) {
mHistogramEnabled = false;
@@ -1689,7 +1691,12 @@ public class PhotoModule
}
if (animateBefore) {
- animateAfterShutter();
+ mActivity.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ animateAfterShutter();
+ }
+ });
}
if (mCameraState == LONGSHOT) {
diff --git a/src/com/android/camera/PhotoUI.java b/src/com/android/camera/PhotoUI.java
index 5aeccac..38c6497 100644
--- a/src/com/android/camera/PhotoUI.java
+++ b/src/com/android/camera/PhotoUI.java
@@ -83,7 +83,6 @@ public class PhotoUI extends BaseUI implements PieListener,
private static final String TAG = "CAM_UI";
private int mDownSampleFactor = 4;
- private final AnimationManager mAnimationManager;
private final FocusRing mFocusRing;
private PhotoController mController;
private PreviewGestures mGestures;
@@ -126,7 +125,6 @@ public class PhotoUI extends BaseUI implements PieListener,
private float mSurfaceTextureUncroppedHeight;
private ImageView mThumbnail;
- private View mFlashOverlay;
private SurfaceTextureSizeChangedListener mSurfaceTextureSizeListener;
private SurfaceView mSurfaceView = null;
@@ -251,7 +249,6 @@ public class PhotoUI extends BaseUI implements PieListener,
});
mRenderOverlay = (RenderOverlay) mRootView.findViewById(R.id.render_overlay);
- mFlashOverlay = mRootView.findViewById(R.id.flash_overlay);
mShutterButton = (ShutterButton) mRootView.findViewById(R.id.shutter_button);
mMenuButton = mRootView.findViewById(R.id.menu);
@@ -266,7 +263,6 @@ public class PhotoUI extends BaseUI implements PieListener,
}
mFocusRing = (FocusRing) mRootView.findViewById(R.id.focus_ring);
initIndicators();
- mAnimationManager = new AnimationManager();
mOrientationResize = false;
mPrevOrientationResize = false;
@@ -435,6 +431,8 @@ public class PhotoUI extends BaseUI implements PieListener,
RectF r = new RectF(mSurfaceView.getLeft(), mSurfaceView.getTop(),
mSurfaceView.getRight(), mSurfaceView.getBottom());
mController.onPreviewRectChanged(CameraUtil.rectFToRect(r));
+
+ onPreviewRectChanged(r);
}
@Override
@@ -672,10 +670,6 @@ public class PhotoUI extends BaseUI implements PieListener,
public void setCameraState(int state) {
}
- public void animateFlash() {
- mAnimationManager.startFlashAnimation(mFlashOverlay);
- }
-
public void enableGestures(boolean enable) {
if (mGestures != null) {
mGestures.setEnabled(enable);
diff --git a/src/com/android/camera/VideoModule.java b/src/com/android/camera/VideoModule.java
index 8f57777..56ae96d 100644
--- a/src/com/android/camera/VideoModule.java
+++ b/src/com/android/camera/VideoModule.java
@@ -833,8 +833,7 @@ public class VideoModule implements CameraModule,
// the preview. This will cause the preview flicker since the preview
// will not be continuous for a short period of time.
- mUI.animateFlash();
- mUI.animateCapture();
+ mUI.animateFlash(false);
}
}
mUI.showUIafterRecording();
@@ -2006,7 +2005,6 @@ public class VideoModule implements CameraModule,
private boolean startVideoRecording() {
Log.v(TAG, "startVideoRecording");
mStartRecPending = true;
- mUI.cancelAnimations();
mUI.setSwipingEnabled(false);
mUI.hideUIwhileRecording();
// When recording request is sent before starting preview, onPreviewFrame()
@@ -3107,8 +3105,7 @@ public class VideoModule implements CameraModule,
if (mParameters == null) return;
if (CameraUtil.isVideoSnapshotSupported(mParameters) && !mIsVideoCaptureIntent) {
if (enabled) {
- mUI.animateFlash();
- mUI.animateCapture();
+ mUI.animateFlash(true);
} else {
mUI.showPreviewBorder(enabled);
}
diff --git a/src/com/android/camera/VideoUI.java b/src/com/android/camera/VideoUI.java
index 4107af2..6eff51e 100644
--- a/src/com/android/camera/VideoUI.java
+++ b/src/com/android/camera/VideoUI.java
@@ -24,6 +24,7 @@ import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Point;
+import android.graphics.RectF;
import android.graphics.drawable.ColorDrawable;
import android.hardware.Camera.Parameters;
import android.hardware.Camera.Face;
@@ -99,7 +100,6 @@ public class VideoUI extends BaseUI implements PieRenderer.PieListener,
private int mZoomMax;
private List<Integer> mZoomRatios;
private ImageView mThumbnail;
- private View mFlashOverlay;
private boolean mOrientationResize;
private boolean mPrevOrientationResize;
private boolean mIsTimeLapse = false;
@@ -112,7 +112,6 @@ public class VideoUI extends BaseUI implements PieRenderer.PieListener,
private int mMaxPreviewHeight = 0;
private float mAspectRatio = 4f / 3f;
private boolean mAspectRatioResize;
- private final AnimationManager mAnimationManager;
private int mPreviewOrientation = -1;
private int mOrientation;
@@ -215,7 +214,6 @@ public class VideoUI extends BaseUI implements PieRenderer.PieListener,
});
mFocusRing = (FocusRing) mRootView.findViewById(R.id.focus_ring);
- mFlashOverlay = mRootView.findViewById(R.id.flash_overlay);
mShutterButton = (ShutterButton) mRootView.findViewById(R.id.shutter_button);
mMuteButton = (RotateImageView)mRootView.findViewById(R.id.mute_button);
@@ -249,7 +247,6 @@ public class VideoUI extends BaseUI implements PieRenderer.PieListener,
mFaceView = (FaceView) mRootView.findViewById(R.id.face_view);
setSurfaceTextureSizeChangedListener(mFaceView);
}
- mAnimationManager = new AnimationManager();
mOrientationResize = false;
mPrevOrientationResize = false;
@@ -456,41 +453,6 @@ public class VideoUI extends BaseUI implements PieRenderer.PieListener,
}
}
- /**
- * Starts a flash animation
- */
- public void animateFlash() {
- mAnimationManager.startFlashAnimation(mFlashOverlay);
- }
-
- /**
- * Starts a capture animation
- */
- public void animateCapture() {
- Bitmap bitmap = null;
- animateCapture(bitmap);
- }
-
- /**
- * Starts a capture animation
- * @param bitmap the captured image that we shrink and slide in the animation
- */
- public void animateCapture(Bitmap bitmap) {
- if (bitmap == null) {
- Log.e(TAG, "No valid bitmap for capture animation.");
- return;
- }
- mActivity.updateThumbnail(bitmap);
- mAnimationManager.startCaptureAnimation(mThumbnail);
- }
-
- /**
- * Cancels on-going animations
- */
- public void cancelAnimations() {
- mAnimationManager.cancelAnimations();
- }
-
public boolean collapseCameraControls() {
boolean ret = false;
mCameraControls.collapse();
@@ -1066,6 +1028,10 @@ public class VideoUI extends BaseUI implements PieRenderer.PieListener,
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
Log.v(TAG, "surfaceChanged: width = " + width + ", height = " + height);
+
+ RectF r = new RectF(mSurfaceView.getLeft(), mSurfaceView.getTop(),
+ mSurfaceView.getRight(), mSurfaceView.getBottom());
+ onPreviewRectChanged(r);
}
@Override
diff --git a/src/com/android/camera/ui/CaptureAnimationOverlay.java b/src/com/android/camera/ui/CaptureAnimationOverlay.java
new file mode 100644
index 0000000..36c9a11
--- /dev/null
+++ b/src/com/android/camera/ui/CaptureAnimationOverlay.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.camera.ui;
+
+import android.animation.Animator;
+import android.animation.AnimatorSet;
+import android.animation.ValueAnimator;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.RectF;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.animation.Interpolator;
+import android.view.animation.LinearInterpolator;
+
+/**
+ * This class handles all the animations at capture time. Post capture animations
+ * will be handled in a separate place.
+ */
+public class CaptureAnimationOverlay extends View {
+ private final static String TAG = CaptureAnimationOverlay.class.getSimpleName();
+
+ private final static int FLASH_COLOR = Color.WHITE;
+
+ private static final float FLASH_MAX_ALPHA = 0.85f;
+ private static final long FLASH_FULL_DURATION_MS = 65;
+ private static final long FLASH_DECREASE_DURATION_MS = 150;
+ private static final float SHORT_FLASH_MAX_ALPHA = 0.75f;
+ private static final long SHORT_FLASH_FULL_DURATION_MS = 34;
+ private static final long SHORT_FLASH_DECREASE_DURATION_MS = 100;
+
+ private AnimatorSet mFlashAnimation;
+ private final RectF mPreviewArea = new RectF();
+ private final Paint mPaint = new Paint();
+ private final Interpolator mFlashAnimInterpolator;
+ private final ValueAnimator.AnimatorUpdateListener mFlashAnimUpdateListener;
+ private final Animator.AnimatorListener mFlashAnimListener;
+
+ public CaptureAnimationOverlay(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ mPaint.setColor(FLASH_COLOR);
+ mFlashAnimInterpolator = new LinearInterpolator();
+ mFlashAnimUpdateListener = new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ float alpha = 255.0f * (Float) animation.getAnimatedValue();
+ mPaint.setAlpha((int) alpha);
+ invalidate();
+ }
+ };
+ mFlashAnimListener = new Animator.AnimatorListener() {
+ @Override
+ public void onAnimationStart(Animator animation) {
+ setVisibility(VISIBLE);
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mFlashAnimation = null;
+ setVisibility(GONE);
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ // End is always called after cancel.
+ }
+
+ @Override
+ public void onAnimationRepeat(Animator animation) {
+
+ }
+ };
+ }
+
+ /**
+ * Start flash animation.
+ *
+ * @param shortFlash show shortest possible flash instead of regular long version.
+ */
+ public void startFlashAnimation(boolean shortFlash) {
+ if (mFlashAnimation != null && mFlashAnimation.isRunning()) {
+ mFlashAnimation.cancel();
+ }
+ float maxAlpha;
+
+ if (shortFlash) {
+ maxAlpha = SHORT_FLASH_MAX_ALPHA;
+ } else {
+ maxAlpha = FLASH_MAX_ALPHA;
+ }
+
+ ValueAnimator flashAnim1 = ValueAnimator.ofFloat(maxAlpha, maxAlpha);
+ ValueAnimator flashAnim2 = ValueAnimator.ofFloat(maxAlpha, .0f);
+
+ if (shortFlash) {
+ flashAnim1.setDuration(SHORT_FLASH_FULL_DURATION_MS);
+ flashAnim2.setDuration(SHORT_FLASH_DECREASE_DURATION_MS);
+ } else {
+ flashAnim1.setDuration(FLASH_FULL_DURATION_MS);
+ flashAnim2.setDuration(FLASH_DECREASE_DURATION_MS);
+ }
+
+ flashAnim1.addUpdateListener(mFlashAnimUpdateListener);
+ flashAnim2.addUpdateListener(mFlashAnimUpdateListener);
+ flashAnim1.setInterpolator(mFlashAnimInterpolator);
+ flashAnim2.setInterpolator(mFlashAnimInterpolator);
+
+ mFlashAnimation = new AnimatorSet();
+ mFlashAnimation.play(flashAnim1).before(flashAnim2);
+ mFlashAnimation.addListener(mFlashAnimListener);
+ mFlashAnimation.start();
+ }
+
+ @Override
+ public void onDraw(Canvas canvas) {
+ if (mFlashAnimation != null && mFlashAnimation.isRunning()) {
+ // mPaint alpha is animated by the animation.
+ canvas.drawRect(mPreviewArea, mPaint);
+ canvas.clipRect(mPreviewArea);
+ }
+ }
+
+ @Override
+ public boolean hasOverlappingRendering() {
+ // The internal draw method will NOT have draw calls that overlap.
+ return false;
+ }
+
+ public void setPreviewRect(RectF previewArea) {
+ mPreviewArea.set(previewArea);
+ }
+}