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