PeekView.java revision d02de7808c906f89c1d331feebcefba6696d8668
15052117cc429d85cf446421ca74859f4365747d3Angus Kong/* 25052117cc429d85cf446421ca74859f4365747d3Angus Kong * Copyright (C) 2014 The Android Open Source Project 35052117cc429d85cf446421ca74859f4365747d3Angus Kong * 45052117cc429d85cf446421ca74859f4365747d3Angus Kong * Licensed under the Apache License, Version 2.0 (the "License"); 55052117cc429d85cf446421ca74859f4365747d3Angus Kong * you may not use this file except in compliance with the License. 65052117cc429d85cf446421ca74859f4365747d3Angus Kong * You may obtain a copy of the License at 75052117cc429d85cf446421ca74859f4365747d3Angus Kong * 85052117cc429d85cf446421ca74859f4365747d3Angus Kong * http://www.apache.org/licenses/LICENSE-2.0 95052117cc429d85cf446421ca74859f4365747d3Angus Kong * 105052117cc429d85cf446421ca74859f4365747d3Angus Kong * Unless required by applicable law or agreed to in writing, software 115052117cc429d85cf446421ca74859f4365747d3Angus Kong * distributed under the License is distributed on an "AS IS" BASIS, 125052117cc429d85cf446421ca74859f4365747d3Angus Kong * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 135052117cc429d85cf446421ca74859f4365747d3Angus Kong * See the License for the specific language governing permissions and 145052117cc429d85cf446421ca74859f4365747d3Angus Kong * limitations under the License. 155052117cc429d85cf446421ca74859f4365747d3Angus Kong */ 165052117cc429d85cf446421ca74859f4365747d3Angus Kong 175052117cc429d85cf446421ca74859f4365747d3Angus Kongpackage com.android.camera.widget; 185052117cc429d85cf446421ca74859f4365747d3Angus Kong 195052117cc429d85cf446421ca74859f4365747d3Angus Kongimport android.animation.Animator; 205052117cc429d85cf446421ca74859f4365747d3Angus Kongimport android.animation.AnimatorSet; 215052117cc429d85cf446421ca74859f4365747d3Angus Kongimport android.animation.ValueAnimator; 225052117cc429d85cf446421ca74859f4365747d3Angus Kongimport android.content.Context; 235052117cc429d85cf446421ca74859f4365747d3Angus Kongimport android.graphics.Bitmap; 24c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kongimport android.graphics.Canvas; 255052117cc429d85cf446421ca74859f4365747d3Angus Kongimport android.graphics.Point; 26c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kongimport android.graphics.Rect; 275052117cc429d85cf446421ca74859f4365747d3Angus Kongimport android.graphics.drawable.BitmapDrawable; 28c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kongimport android.graphics.drawable.Drawable; 295052117cc429d85cf446421ca74859f4365747d3Angus Kongimport android.util.AttributeSet; 305052117cc429d85cf446421ca74859f4365747d3Angus Kongimport android.view.animation.AccelerateInterpolator; 315052117cc429d85cf446421ca74859f4365747d3Angus Kongimport android.view.animation.DecelerateInterpolator; 325052117cc429d85cf446421ca74859f4365747d3Angus Kongimport android.widget.ImageView; 335052117cc429d85cf446421ca74859f4365747d3Angus Kong 34c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kongimport com.android.camera.util.CameraUtil; 35c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong 365052117cc429d85cf446421ca74859f4365747d3Angus Kong/** 375052117cc429d85cf446421ca74859f4365747d3Angus Kong * An ImageView which has the built-in peek animation support. 385052117cc429d85cf446421ca74859f4365747d3Angus Kong */ 395052117cc429d85cf446421ca74859f4365747d3Angus Kongpublic class PeekView extends ImageView { 405052117cc429d85cf446421ca74859f4365747d3Angus Kong 41d02de7808c906f89c1d331feebcefba6696d8668Angus Kong private static final float ROTATE_ANGLE = -7f; 42c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong private static final long PEEK_IN_DURATION_MS = 200; 43c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong private static final long PEEK_STAY_DURATION_MS = 100; 44c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong private static final long PEEK_OUT_DURATION_MS = 200; 45c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong private static final float FILMSTRIP_SCALE = 0.7f; 465052117cc429d85cf446421ca74859f4365747d3Angus Kong 475052117cc429d85cf446421ca74859f4365747d3Angus Kong private AnimatorSet mPeekAnimator; 485052117cc429d85cf446421ca74859f4365747d3Angus Kong private float mPeekRotateAngle; 495052117cc429d85cf446421ca74859f4365747d3Angus Kong private Point mRotationPivot; 505052117cc429d85cf446421ca74859f4365747d3Angus Kong private float mRotateScale; 515052117cc429d85cf446421ca74859f4365747d3Angus Kong private boolean mAnimationCanceled; 52c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong private Drawable mImageDrawable; 53c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong private Rect mDrawableBound; 545052117cc429d85cf446421ca74859f4365747d3Angus Kong 555052117cc429d85cf446421ca74859f4365747d3Angus Kong public PeekView(Context context) { 565052117cc429d85cf446421ca74859f4365747d3Angus Kong super(context); 575052117cc429d85cf446421ca74859f4365747d3Angus Kong init(); 585052117cc429d85cf446421ca74859f4365747d3Angus Kong } 595052117cc429d85cf446421ca74859f4365747d3Angus Kong 605052117cc429d85cf446421ca74859f4365747d3Angus Kong public PeekView(Context context, AttributeSet attrs) { 615052117cc429d85cf446421ca74859f4365747d3Angus Kong super(context, attrs); 625052117cc429d85cf446421ca74859f4365747d3Angus Kong init(); 635052117cc429d85cf446421ca74859f4365747d3Angus Kong } 645052117cc429d85cf446421ca74859f4365747d3Angus Kong 655052117cc429d85cf446421ca74859f4365747d3Angus Kong public PeekView(Context context, AttributeSet attrs, int defStyle) { 665052117cc429d85cf446421ca74859f4365747d3Angus Kong super(context, attrs, defStyle); 675052117cc429d85cf446421ca74859f4365747d3Angus Kong init(); 685052117cc429d85cf446421ca74859f4365747d3Angus Kong } 695052117cc429d85cf446421ca74859f4365747d3Angus Kong 705052117cc429d85cf446421ca74859f4365747d3Angus Kong private void init() { 715052117cc429d85cf446421ca74859f4365747d3Angus Kong mRotationPivot = new Point(); 72c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong } 73c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong 74c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong @Override 75c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong protected void onDraw(Canvas c) { 76c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong super.onDraw(c); 77c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong if (mImageDrawable == null) { 78c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong return; 79c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong } 80c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong c.save(); 81c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong c.rotate(mPeekRotateAngle, mRotationPivot.x, mRotationPivot.y); 82c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong mImageDrawable.setBounds(mDrawableBound); 83c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong mImageDrawable.draw(c); 84c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong c.restore(); 85c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong } 86c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong 87c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong /** 88c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong * Starts the peek animation. 89c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong * 90c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong * @param bitmap The bitmap for the animation. 91c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong * @param strong {@code true} if the animation is the strong version which 92c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong * shows more portion of the bitmap. 93c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong */ 94c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong public void startPeekAnimation(final Bitmap bitmap, boolean strong) { 955052117cc429d85cf446421ca74859f4365747d3Angus Kong ValueAnimator.AnimatorUpdateListener updateListener = 965052117cc429d85cf446421ca74859f4365747d3Angus Kong new ValueAnimator.AnimatorUpdateListener() { 975052117cc429d85cf446421ca74859f4365747d3Angus Kong @Override 985052117cc429d85cf446421ca74859f4365747d3Angus Kong public void onAnimationUpdate(ValueAnimator valueAnimator) { 995052117cc429d85cf446421ca74859f4365747d3Angus Kong mPeekRotateAngle = mRotateScale * (Float) valueAnimator.getAnimatedValue(); 100c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong invalidate(); 1015052117cc429d85cf446421ca74859f4365747d3Angus Kong } 1025052117cc429d85cf446421ca74859f4365747d3Angus Kong }; 1035052117cc429d85cf446421ca74859f4365747d3Angus Kong ValueAnimator peekAnimateIn = ValueAnimator.ofFloat(0f, ROTATE_ANGLE); 1045052117cc429d85cf446421ca74859f4365747d3Angus Kong ValueAnimator peekAnimateStay = ValueAnimator.ofFloat(ROTATE_ANGLE, ROTATE_ANGLE); 1055052117cc429d85cf446421ca74859f4365747d3Angus Kong ValueAnimator peekAnimateOut = ValueAnimator.ofFloat(ROTATE_ANGLE, 0f); 1065052117cc429d85cf446421ca74859f4365747d3Angus Kong peekAnimateIn.addUpdateListener(updateListener); 1075052117cc429d85cf446421ca74859f4365747d3Angus Kong peekAnimateOut.addUpdateListener(updateListener); 1085052117cc429d85cf446421ca74859f4365747d3Angus Kong peekAnimateIn.setDuration(PEEK_IN_DURATION_MS); 1095052117cc429d85cf446421ca74859f4365747d3Angus Kong peekAnimateStay.setDuration(PEEK_STAY_DURATION_MS); 1105052117cc429d85cf446421ca74859f4365747d3Angus Kong peekAnimateOut.setDuration(PEEK_OUT_DURATION_MS); 1115052117cc429d85cf446421ca74859f4365747d3Angus Kong peekAnimateIn.setInterpolator(new DecelerateInterpolator()); 1125052117cc429d85cf446421ca74859f4365747d3Angus Kong peekAnimateOut.setInterpolator(new AccelerateInterpolator()); 1135052117cc429d85cf446421ca74859f4365747d3Angus Kong mPeekAnimator = new AnimatorSet(); 1145052117cc429d85cf446421ca74859f4365747d3Angus Kong mPeekAnimator.playSequentially(peekAnimateIn, peekAnimateStay, peekAnimateOut); 1155052117cc429d85cf446421ca74859f4365747d3Angus Kong mPeekAnimator.addListener(new Animator.AnimatorListener() { 1165052117cc429d85cf446421ca74859f4365747d3Angus Kong @Override 1175052117cc429d85cf446421ca74859f4365747d3Angus Kong public void onAnimationStart(Animator animator) { 1185052117cc429d85cf446421ca74859f4365747d3Angus Kong setVisibility(VISIBLE); 1195052117cc429d85cf446421ca74859f4365747d3Angus Kong mAnimationCanceled = false; 1205052117cc429d85cf446421ca74859f4365747d3Angus Kong invalidate(); 1215052117cc429d85cf446421ca74859f4365747d3Angus Kong } 1225052117cc429d85cf446421ca74859f4365747d3Angus Kong 1235052117cc429d85cf446421ca74859f4365747d3Angus Kong @Override 1245052117cc429d85cf446421ca74859f4365747d3Angus Kong public void onAnimationEnd(Animator animator) { 1255052117cc429d85cf446421ca74859f4365747d3Angus Kong if (!mAnimationCanceled) { 1265052117cc429d85cf446421ca74859f4365747d3Angus Kong clear(); 1275052117cc429d85cf446421ca74859f4365747d3Angus Kong } 1285052117cc429d85cf446421ca74859f4365747d3Angus Kong } 1295052117cc429d85cf446421ca74859f4365747d3Angus Kong 1305052117cc429d85cf446421ca74859f4365747d3Angus Kong @Override 1315052117cc429d85cf446421ca74859f4365747d3Angus Kong public void onAnimationCancel(Animator animator) { 1325052117cc429d85cf446421ca74859f4365747d3Angus Kong mAnimationCanceled = true; 1335052117cc429d85cf446421ca74859f4365747d3Angus Kong } 1345052117cc429d85cf446421ca74859f4365747d3Angus Kong 1355052117cc429d85cf446421ca74859f4365747d3Angus Kong @Override 1365052117cc429d85cf446421ca74859f4365747d3Angus Kong public void onAnimationRepeat(Animator animator) { 1375052117cc429d85cf446421ca74859f4365747d3Angus Kong 1385052117cc429d85cf446421ca74859f4365747d3Angus Kong } 1395052117cc429d85cf446421ca74859f4365747d3Angus Kong }); 1405052117cc429d85cf446421ca74859f4365747d3Angus Kong 1415052117cc429d85cf446421ca74859f4365747d3Angus Kong mRotateScale = (strong ? 1.0f : 0.5f); 142c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong mImageDrawable = new BitmapDrawable(getResources(), bitmap); 143c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong Point drawDim = CameraUtil.resizeToFill(mImageDrawable.getIntrinsicWidth(), 144c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong mImageDrawable.getIntrinsicHeight(), 0, (int) (getWidth() * FILMSTRIP_SCALE), 145c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong (int) (getHeight() * FILMSTRIP_SCALE)); 146c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong int x = getMeasuredWidth(); 147c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong int y = (getMeasuredHeight() - drawDim.y) / 2; 148c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong mDrawableBound = new Rect(x, y, x + drawDim.x, y + drawDim.y); 149c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong mRotationPivot.set(x, (int) (y + drawDim.y * 1.1)); 1505052117cc429d85cf446421ca74859f4365747d3Angus Kong mPeekAnimator.start(); 1515052117cc429d85cf446421ca74859f4365747d3Angus Kong } 1525052117cc429d85cf446421ca74859f4365747d3Angus Kong 1535052117cc429d85cf446421ca74859f4365747d3Angus Kong /** 1545052117cc429d85cf446421ca74859f4365747d3Angus Kong * @return whether the animation is running. 1555052117cc429d85cf446421ca74859f4365747d3Angus Kong */ 1565052117cc429d85cf446421ca74859f4365747d3Angus Kong public boolean isPeekAnimationRunning() { 1575052117cc429d85cf446421ca74859f4365747d3Angus Kong return mPeekAnimator.isRunning(); 1585052117cc429d85cf446421ca74859f4365747d3Angus Kong } 1595052117cc429d85cf446421ca74859f4365747d3Angus Kong 1605052117cc429d85cf446421ca74859f4365747d3Angus Kong /** 1615052117cc429d85cf446421ca74859f4365747d3Angus Kong * Stops the animation. See {@link android.animation.Animator#end()}. 1625052117cc429d85cf446421ca74859f4365747d3Angus Kong */ 1635052117cc429d85cf446421ca74859f4365747d3Angus Kong public void stopPeekAnimation() { 1645052117cc429d85cf446421ca74859f4365747d3Angus Kong if (isPeekAnimationRunning()) { 1655052117cc429d85cf446421ca74859f4365747d3Angus Kong mPeekAnimator.end(); 1665052117cc429d85cf446421ca74859f4365747d3Angus Kong } else { 1675052117cc429d85cf446421ca74859f4365747d3Angus Kong clear(); 1685052117cc429d85cf446421ca74859f4365747d3Angus Kong } 1695052117cc429d85cf446421ca74859f4365747d3Angus Kong } 1705052117cc429d85cf446421ca74859f4365747d3Angus Kong 1715052117cc429d85cf446421ca74859f4365747d3Angus Kong /** 1725052117cc429d85cf446421ca74859f4365747d3Angus Kong * Cancels the animation. See {@link android.animation.Animator#cancel()}. 1735052117cc429d85cf446421ca74859f4365747d3Angus Kong */ 1745052117cc429d85cf446421ca74859f4365747d3Angus Kong public void cancelPeekAnimation() { 1755052117cc429d85cf446421ca74859f4365747d3Angus Kong if (isPeekAnimationRunning()) { 1765052117cc429d85cf446421ca74859f4365747d3Angus Kong mPeekAnimator.cancel(); 1775052117cc429d85cf446421ca74859f4365747d3Angus Kong } else { 1785052117cc429d85cf446421ca74859f4365747d3Angus Kong clear(); 1795052117cc429d85cf446421ca74859f4365747d3Angus Kong } 1805052117cc429d85cf446421ca74859f4365747d3Angus Kong } 1815052117cc429d85cf446421ca74859f4365747d3Angus Kong 1825052117cc429d85cf446421ca74859f4365747d3Angus Kong private void clear() { 1835052117cc429d85cf446421ca74859f4365747d3Angus Kong setVisibility(INVISIBLE); 1845052117cc429d85cf446421ca74859f4365747d3Angus Kong setImageDrawable(null); 1855052117cc429d85cf446421ca74859f4365747d3Angus Kong } 1865052117cc429d85cf446421ca74859f4365747d3Angus Kong} 187