PeekView.java revision c195e7a9208c90d7a55e184d4b2b9c747e9c90f1
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 415052117cc429d85cf446421ca74859f4365747d3Angus Kong private static final float ROTATE_ANGLE = -15f; 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 onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 76c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong super.onMeasure(widthMeasureSpec, heightMeasureSpec); 77c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong } 78c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong 79c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong @Override 80c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong protected void onDraw(Canvas c) { 81c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong super.onDraw(c); 82c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong if (mImageDrawable == null) { 83c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong return; 84c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong } 85c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong c.save(); 86c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong c.rotate(mPeekRotateAngle, mRotationPivot.x, mRotationPivot.y); 87c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong mImageDrawable.setBounds(mDrawableBound); 88c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong mImageDrawable.draw(c); 89c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong c.restore(); 90c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong } 91c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong 92c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong /** 93c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong * Starts the peek animation. 94c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong * 95c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong * @param bitmap The bitmap for the animation. 96c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong * @param strong {@code true} if the animation is the strong version which 97c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong * shows more portion of the bitmap. 98c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong */ 99c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong public void startPeekAnimation(final Bitmap bitmap, boolean strong) { 1005052117cc429d85cf446421ca74859f4365747d3Angus Kong ValueAnimator.AnimatorUpdateListener updateListener = 1015052117cc429d85cf446421ca74859f4365747d3Angus Kong new ValueAnimator.AnimatorUpdateListener() { 1025052117cc429d85cf446421ca74859f4365747d3Angus Kong @Override 1035052117cc429d85cf446421ca74859f4365747d3Angus Kong public void onAnimationUpdate(ValueAnimator valueAnimator) { 1045052117cc429d85cf446421ca74859f4365747d3Angus Kong mPeekRotateAngle = mRotateScale * (Float) valueAnimator.getAnimatedValue(); 105c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong invalidate(); 1065052117cc429d85cf446421ca74859f4365747d3Angus Kong } 1075052117cc429d85cf446421ca74859f4365747d3Angus Kong }; 1085052117cc429d85cf446421ca74859f4365747d3Angus Kong ValueAnimator peekAnimateIn = ValueAnimator.ofFloat(0f, ROTATE_ANGLE); 1095052117cc429d85cf446421ca74859f4365747d3Angus Kong ValueAnimator peekAnimateStay = ValueAnimator.ofFloat(ROTATE_ANGLE, ROTATE_ANGLE); 1105052117cc429d85cf446421ca74859f4365747d3Angus Kong ValueAnimator peekAnimateOut = ValueAnimator.ofFloat(ROTATE_ANGLE, 0f); 1115052117cc429d85cf446421ca74859f4365747d3Angus Kong peekAnimateIn.addUpdateListener(updateListener); 1125052117cc429d85cf446421ca74859f4365747d3Angus Kong peekAnimateOut.addUpdateListener(updateListener); 1135052117cc429d85cf446421ca74859f4365747d3Angus Kong peekAnimateIn.setDuration(PEEK_IN_DURATION_MS); 1145052117cc429d85cf446421ca74859f4365747d3Angus Kong peekAnimateStay.setDuration(PEEK_STAY_DURATION_MS); 1155052117cc429d85cf446421ca74859f4365747d3Angus Kong peekAnimateOut.setDuration(PEEK_OUT_DURATION_MS); 1165052117cc429d85cf446421ca74859f4365747d3Angus Kong peekAnimateIn.setInterpolator(new DecelerateInterpolator()); 1175052117cc429d85cf446421ca74859f4365747d3Angus Kong peekAnimateOut.setInterpolator(new AccelerateInterpolator()); 1185052117cc429d85cf446421ca74859f4365747d3Angus Kong mPeekAnimator = new AnimatorSet(); 1195052117cc429d85cf446421ca74859f4365747d3Angus Kong mPeekAnimator.playSequentially(peekAnimateIn, peekAnimateStay, peekAnimateOut); 1205052117cc429d85cf446421ca74859f4365747d3Angus Kong mPeekAnimator.addListener(new Animator.AnimatorListener() { 1215052117cc429d85cf446421ca74859f4365747d3Angus Kong @Override 1225052117cc429d85cf446421ca74859f4365747d3Angus Kong public void onAnimationStart(Animator animator) { 1235052117cc429d85cf446421ca74859f4365747d3Angus Kong setVisibility(VISIBLE); 1245052117cc429d85cf446421ca74859f4365747d3Angus Kong mAnimationCanceled = false; 1255052117cc429d85cf446421ca74859f4365747d3Angus Kong invalidate(); 1265052117cc429d85cf446421ca74859f4365747d3Angus Kong } 1275052117cc429d85cf446421ca74859f4365747d3Angus Kong 1285052117cc429d85cf446421ca74859f4365747d3Angus Kong @Override 1295052117cc429d85cf446421ca74859f4365747d3Angus Kong public void onAnimationEnd(Animator animator) { 1305052117cc429d85cf446421ca74859f4365747d3Angus Kong if (!mAnimationCanceled) { 1315052117cc429d85cf446421ca74859f4365747d3Angus Kong clear(); 1325052117cc429d85cf446421ca74859f4365747d3Angus Kong } 1335052117cc429d85cf446421ca74859f4365747d3Angus Kong } 1345052117cc429d85cf446421ca74859f4365747d3Angus Kong 1355052117cc429d85cf446421ca74859f4365747d3Angus Kong @Override 1365052117cc429d85cf446421ca74859f4365747d3Angus Kong public void onAnimationCancel(Animator animator) { 1375052117cc429d85cf446421ca74859f4365747d3Angus Kong mAnimationCanceled = true; 1385052117cc429d85cf446421ca74859f4365747d3Angus Kong } 1395052117cc429d85cf446421ca74859f4365747d3Angus Kong 1405052117cc429d85cf446421ca74859f4365747d3Angus Kong @Override 1415052117cc429d85cf446421ca74859f4365747d3Angus Kong public void onAnimationRepeat(Animator animator) { 1425052117cc429d85cf446421ca74859f4365747d3Angus Kong 1435052117cc429d85cf446421ca74859f4365747d3Angus Kong } 1445052117cc429d85cf446421ca74859f4365747d3Angus Kong }); 1455052117cc429d85cf446421ca74859f4365747d3Angus Kong 1465052117cc429d85cf446421ca74859f4365747d3Angus Kong mRotateScale = (strong ? 1.0f : 0.5f); 147c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong mImageDrawable = new BitmapDrawable(getResources(), bitmap); 148c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong Point drawDim = CameraUtil.resizeToFill(mImageDrawable.getIntrinsicWidth(), 149c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong mImageDrawable.getIntrinsicHeight(), 0, (int) (getWidth() * FILMSTRIP_SCALE), 150c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong (int) (getHeight() * FILMSTRIP_SCALE)); 151c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong int x = getMeasuredWidth(); 152c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong int y = (getMeasuredHeight() - drawDim.y) / 2; 153c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong mDrawableBound = new Rect(x, y, x + drawDim.x, y + drawDim.y); 154c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong mRotationPivot.set(x, (int) (y + drawDim.y * 1.1)); 1555052117cc429d85cf446421ca74859f4365747d3Angus Kong mPeekAnimator.start(); 1565052117cc429d85cf446421ca74859f4365747d3Angus Kong } 1575052117cc429d85cf446421ca74859f4365747d3Angus Kong 1585052117cc429d85cf446421ca74859f4365747d3Angus Kong /** 1595052117cc429d85cf446421ca74859f4365747d3Angus Kong * @return whether the animation is running. 1605052117cc429d85cf446421ca74859f4365747d3Angus Kong */ 1615052117cc429d85cf446421ca74859f4365747d3Angus Kong public boolean isPeekAnimationRunning() { 1625052117cc429d85cf446421ca74859f4365747d3Angus Kong return mPeekAnimator.isRunning(); 1635052117cc429d85cf446421ca74859f4365747d3Angus Kong } 1645052117cc429d85cf446421ca74859f4365747d3Angus Kong 1655052117cc429d85cf446421ca74859f4365747d3Angus Kong /** 1665052117cc429d85cf446421ca74859f4365747d3Angus Kong * Stops the animation. See {@link android.animation.Animator#end()}. 1675052117cc429d85cf446421ca74859f4365747d3Angus Kong */ 1685052117cc429d85cf446421ca74859f4365747d3Angus Kong public void stopPeekAnimation() { 1695052117cc429d85cf446421ca74859f4365747d3Angus Kong if (isPeekAnimationRunning()) { 1705052117cc429d85cf446421ca74859f4365747d3Angus Kong mPeekAnimator.end(); 1715052117cc429d85cf446421ca74859f4365747d3Angus Kong } else { 1725052117cc429d85cf446421ca74859f4365747d3Angus Kong clear(); 1735052117cc429d85cf446421ca74859f4365747d3Angus Kong } 1745052117cc429d85cf446421ca74859f4365747d3Angus Kong } 1755052117cc429d85cf446421ca74859f4365747d3Angus Kong 1765052117cc429d85cf446421ca74859f4365747d3Angus Kong /** 1775052117cc429d85cf446421ca74859f4365747d3Angus Kong * Cancels the animation. See {@link android.animation.Animator#cancel()}. 1785052117cc429d85cf446421ca74859f4365747d3Angus Kong */ 1795052117cc429d85cf446421ca74859f4365747d3Angus Kong public void cancelPeekAnimation() { 1805052117cc429d85cf446421ca74859f4365747d3Angus Kong if (isPeekAnimationRunning()) { 1815052117cc429d85cf446421ca74859f4365747d3Angus Kong mPeekAnimator.cancel(); 1825052117cc429d85cf446421ca74859f4365747d3Angus Kong } else { 1835052117cc429d85cf446421ca74859f4365747d3Angus Kong clear(); 1845052117cc429d85cf446421ca74859f4365747d3Angus Kong } 1855052117cc429d85cf446421ca74859f4365747d3Angus Kong } 1865052117cc429d85cf446421ca74859f4365747d3Angus Kong 1875052117cc429d85cf446421ca74859f4365747d3Angus Kong private void clear() { 1885052117cc429d85cf446421ca74859f4365747d3Angus Kong setVisibility(INVISIBLE); 1895052117cc429d85cf446421ca74859f4365747d3Angus Kong setImageDrawable(null); 1905052117cc429d85cf446421ca74859f4365747d3Angus Kong } 1915052117cc429d85cf446421ca74859f4365747d3Angus Kong} 192