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;
3575fc98f248f4383e3dc10048bfdf0292fd8dd970Alan Newbergerimport com.android.camera2.R;
36c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong
375052117cc429d85cf446421ca74859f4365747d3Angus Kong/**
385052117cc429d85cf446421ca74859f4365747d3Angus Kong * An ImageView which has the built-in peek animation support.
395052117cc429d85cf446421ca74859f4365747d3Angus Kong */
405052117cc429d85cf446421ca74859f4365747d3Angus Kongpublic class PeekView extends ImageView {
415052117cc429d85cf446421ca74859f4365747d3Angus Kong
42d02de7808c906f89c1d331feebcefba6696d8668Angus Kong    private static final float ROTATE_ANGLE = -7f;
43c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong    private static final long PEEK_IN_DURATION_MS = 200;
44c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong    private static final long PEEK_STAY_DURATION_MS = 100;
45c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong    private static final long PEEK_OUT_DURATION_MS = 200;
46c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong    private static final float FILMSTRIP_SCALE = 0.7f;
475052117cc429d85cf446421ca74859f4365747d3Angus Kong
485052117cc429d85cf446421ca74859f4365747d3Angus Kong    private AnimatorSet mPeekAnimator;
495052117cc429d85cf446421ca74859f4365747d3Angus Kong    private float mPeekRotateAngle;
505052117cc429d85cf446421ca74859f4365747d3Angus Kong    private Point mRotationPivot;
515052117cc429d85cf446421ca74859f4365747d3Angus Kong    private float mRotateScale;
525052117cc429d85cf446421ca74859f4365747d3Angus Kong    private boolean mAnimationCanceled;
53c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong    private Drawable mImageDrawable;
54c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong    private Rect mDrawableBound;
555052117cc429d85cf446421ca74859f4365747d3Angus Kong
565052117cc429d85cf446421ca74859f4365747d3Angus Kong    public PeekView(Context context) {
575052117cc429d85cf446421ca74859f4365747d3Angus Kong        super(context);
585052117cc429d85cf446421ca74859f4365747d3Angus Kong        init();
595052117cc429d85cf446421ca74859f4365747d3Angus Kong    }
605052117cc429d85cf446421ca74859f4365747d3Angus Kong
615052117cc429d85cf446421ca74859f4365747d3Angus Kong    public PeekView(Context context, AttributeSet attrs) {
625052117cc429d85cf446421ca74859f4365747d3Angus Kong        super(context, attrs);
635052117cc429d85cf446421ca74859f4365747d3Angus Kong        init();
645052117cc429d85cf446421ca74859f4365747d3Angus Kong    }
655052117cc429d85cf446421ca74859f4365747d3Angus Kong
665052117cc429d85cf446421ca74859f4365747d3Angus Kong    public PeekView(Context context, AttributeSet attrs, int defStyle) {
675052117cc429d85cf446421ca74859f4365747d3Angus Kong        super(context, attrs, defStyle);
685052117cc429d85cf446421ca74859f4365747d3Angus Kong        init();
695052117cc429d85cf446421ca74859f4365747d3Angus Kong    }
705052117cc429d85cf446421ca74859f4365747d3Angus Kong
715052117cc429d85cf446421ca74859f4365747d3Angus Kong    private void init() {
725052117cc429d85cf446421ca74859f4365747d3Angus Kong        mRotationPivot = new Point();
73c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong    }
74c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong
75c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong    @Override
76c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong    protected void onDraw(Canvas c) {
77c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong        super.onDraw(c);
78c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong        if (mImageDrawable == null) {
79c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong            return;
80c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong        }
81c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong        c.save();
82c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong        c.rotate(mPeekRotateAngle, mRotationPivot.x, mRotationPivot.y);
83c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong        mImageDrawable.setBounds(mDrawableBound);
84c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong        mImageDrawable.draw(c);
85c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong        c.restore();
86c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong    }
87c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong
88c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong    /**
89c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong     * Starts the peek animation.
90c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong     *
91c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong     * @param bitmap The bitmap for the animation.
92c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong     * @param strong {@code true} if the animation is the strong version which
93c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong     *               shows more portion of the bitmap.
94159e6e9ca0d0ecb53d49765c75fd7a0b2afef965Spike Sprague     * @param accessibilityString An accessibility String to be announced
95159e6e9ca0d0ecb53d49765c75fd7a0b2afef965Spike Sprague                     during the peek animation.
96c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong     */
97159e6e9ca0d0ecb53d49765c75fd7a0b2afef965Spike Sprague    public void startPeekAnimation(final Bitmap bitmap, boolean strong,
98159e6e9ca0d0ecb53d49765c75fd7a0b2afef965Spike Sprague            String accessibilityString) {
995052117cc429d85cf446421ca74859f4365747d3Angus Kong        ValueAnimator.AnimatorUpdateListener updateListener =
1005052117cc429d85cf446421ca74859f4365747d3Angus Kong                new ValueAnimator.AnimatorUpdateListener() {
1015052117cc429d85cf446421ca74859f4365747d3Angus Kong                    @Override
1025052117cc429d85cf446421ca74859f4365747d3Angus Kong                    public void onAnimationUpdate(ValueAnimator valueAnimator) {
1035052117cc429d85cf446421ca74859f4365747d3Angus Kong                        mPeekRotateAngle = mRotateScale * (Float) valueAnimator.getAnimatedValue();
104c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong                        invalidate();
1055052117cc429d85cf446421ca74859f4365747d3Angus Kong                    }
1065052117cc429d85cf446421ca74859f4365747d3Angus Kong                };
1075052117cc429d85cf446421ca74859f4365747d3Angus Kong        ValueAnimator peekAnimateIn = ValueAnimator.ofFloat(0f, ROTATE_ANGLE);
1085052117cc429d85cf446421ca74859f4365747d3Angus Kong        ValueAnimator peekAnimateStay = ValueAnimator.ofFloat(ROTATE_ANGLE, ROTATE_ANGLE);
1095052117cc429d85cf446421ca74859f4365747d3Angus Kong        ValueAnimator peekAnimateOut = ValueAnimator.ofFloat(ROTATE_ANGLE, 0f);
1105052117cc429d85cf446421ca74859f4365747d3Angus Kong        peekAnimateIn.addUpdateListener(updateListener);
1115052117cc429d85cf446421ca74859f4365747d3Angus Kong        peekAnimateOut.addUpdateListener(updateListener);
1125052117cc429d85cf446421ca74859f4365747d3Angus Kong        peekAnimateIn.setDuration(PEEK_IN_DURATION_MS);
1135052117cc429d85cf446421ca74859f4365747d3Angus Kong        peekAnimateStay.setDuration(PEEK_STAY_DURATION_MS);
1145052117cc429d85cf446421ca74859f4365747d3Angus Kong        peekAnimateOut.setDuration(PEEK_OUT_DURATION_MS);
1155052117cc429d85cf446421ca74859f4365747d3Angus Kong        peekAnimateIn.setInterpolator(new DecelerateInterpolator());
1165052117cc429d85cf446421ca74859f4365747d3Angus Kong        peekAnimateOut.setInterpolator(new AccelerateInterpolator());
1175052117cc429d85cf446421ca74859f4365747d3Angus Kong        mPeekAnimator = new AnimatorSet();
1185052117cc429d85cf446421ca74859f4365747d3Angus Kong        mPeekAnimator.playSequentially(peekAnimateIn, peekAnimateStay, peekAnimateOut);
1195052117cc429d85cf446421ca74859f4365747d3Angus Kong        mPeekAnimator.addListener(new Animator.AnimatorListener() {
1205052117cc429d85cf446421ca74859f4365747d3Angus Kong            @Override
1215052117cc429d85cf446421ca74859f4365747d3Angus Kong            public void onAnimationStart(Animator animator) {
1225052117cc429d85cf446421ca74859f4365747d3Angus Kong                setVisibility(VISIBLE);
1235052117cc429d85cf446421ca74859f4365747d3Angus Kong                mAnimationCanceled = false;
1245052117cc429d85cf446421ca74859f4365747d3Angus Kong                invalidate();
1255052117cc429d85cf446421ca74859f4365747d3Angus Kong            }
1265052117cc429d85cf446421ca74859f4365747d3Angus Kong
1275052117cc429d85cf446421ca74859f4365747d3Angus Kong            @Override
1285052117cc429d85cf446421ca74859f4365747d3Angus Kong            public void onAnimationEnd(Animator animator) {
1295052117cc429d85cf446421ca74859f4365747d3Angus Kong                if (!mAnimationCanceled) {
1305052117cc429d85cf446421ca74859f4365747d3Angus Kong                    clear();
1315052117cc429d85cf446421ca74859f4365747d3Angus Kong                }
1325052117cc429d85cf446421ca74859f4365747d3Angus Kong            }
1335052117cc429d85cf446421ca74859f4365747d3Angus Kong
1345052117cc429d85cf446421ca74859f4365747d3Angus Kong            @Override
1355052117cc429d85cf446421ca74859f4365747d3Angus Kong            public void onAnimationCancel(Animator animator) {
1365052117cc429d85cf446421ca74859f4365747d3Angus Kong                mAnimationCanceled = true;
1375052117cc429d85cf446421ca74859f4365747d3Angus Kong            }
1385052117cc429d85cf446421ca74859f4365747d3Angus Kong
1395052117cc429d85cf446421ca74859f4365747d3Angus Kong            @Override
1405052117cc429d85cf446421ca74859f4365747d3Angus Kong            public void onAnimationRepeat(Animator animator) {
1415052117cc429d85cf446421ca74859f4365747d3Angus Kong
1425052117cc429d85cf446421ca74859f4365747d3Angus Kong            }
1435052117cc429d85cf446421ca74859f4365747d3Angus Kong        });
1445052117cc429d85cf446421ca74859f4365747d3Angus Kong
1455052117cc429d85cf446421ca74859f4365747d3Angus Kong        mRotateScale = (strong ? 1.0f : 0.5f);
146c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong        mImageDrawable = new BitmapDrawable(getResources(), bitmap);
147c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong        Point drawDim = CameraUtil.resizeToFill(mImageDrawable.getIntrinsicWidth(),
148c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong                mImageDrawable.getIntrinsicHeight(), 0, (int) (getWidth() * FILMSTRIP_SCALE),
149c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong                (int) (getHeight() * FILMSTRIP_SCALE));
150c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong        int x = getMeasuredWidth();
151c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong        int y = (getMeasuredHeight() - drawDim.y) / 2;
152c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong        mDrawableBound = new Rect(x, y, x + drawDim.x, y + drawDim.y);
153c195e7a9208c90d7a55e184d4b2b9c747e9c90f1Angus Kong        mRotationPivot.set(x, (int) (y + drawDim.y * 1.1));
1545052117cc429d85cf446421ca74859f4365747d3Angus Kong        mPeekAnimator.start();
155159e6e9ca0d0ecb53d49765c75fd7a0b2afef965Spike Sprague
156159e6e9ca0d0ecb53d49765c75fd7a0b2afef965Spike Sprague        announceForAccessibility(accessibilityString);
1575052117cc429d85cf446421ca74859f4365747d3Angus Kong    }
1585052117cc429d85cf446421ca74859f4365747d3Angus Kong
1595052117cc429d85cf446421ca74859f4365747d3Angus Kong    /**
1605052117cc429d85cf446421ca74859f4365747d3Angus Kong     * @return whether the animation is running.
1615052117cc429d85cf446421ca74859f4365747d3Angus Kong     */
1625052117cc429d85cf446421ca74859f4365747d3Angus Kong    public boolean isPeekAnimationRunning() {
1635052117cc429d85cf446421ca74859f4365747d3Angus Kong        return mPeekAnimator.isRunning();
1645052117cc429d85cf446421ca74859f4365747d3Angus Kong    }
1655052117cc429d85cf446421ca74859f4365747d3Angus Kong
1665052117cc429d85cf446421ca74859f4365747d3Angus Kong    /**
1675052117cc429d85cf446421ca74859f4365747d3Angus Kong     * Stops the animation. See {@link android.animation.Animator#end()}.
1685052117cc429d85cf446421ca74859f4365747d3Angus Kong     */
1695052117cc429d85cf446421ca74859f4365747d3Angus Kong    public void stopPeekAnimation() {
1705052117cc429d85cf446421ca74859f4365747d3Angus Kong        if (isPeekAnimationRunning()) {
1715052117cc429d85cf446421ca74859f4365747d3Angus Kong            mPeekAnimator.end();
1725052117cc429d85cf446421ca74859f4365747d3Angus Kong        } else {
1735052117cc429d85cf446421ca74859f4365747d3Angus Kong            clear();
1745052117cc429d85cf446421ca74859f4365747d3Angus Kong        }
1755052117cc429d85cf446421ca74859f4365747d3Angus Kong    }
1765052117cc429d85cf446421ca74859f4365747d3Angus Kong
1775052117cc429d85cf446421ca74859f4365747d3Angus Kong    /**
1785052117cc429d85cf446421ca74859f4365747d3Angus Kong     * Cancels the animation. See {@link android.animation.Animator#cancel()}.
1795052117cc429d85cf446421ca74859f4365747d3Angus Kong     */
1805052117cc429d85cf446421ca74859f4365747d3Angus Kong    public void cancelPeekAnimation() {
1815052117cc429d85cf446421ca74859f4365747d3Angus Kong        if (isPeekAnimationRunning()) {
1825052117cc429d85cf446421ca74859f4365747d3Angus Kong            mPeekAnimator.cancel();
1835052117cc429d85cf446421ca74859f4365747d3Angus Kong        } else {
1845052117cc429d85cf446421ca74859f4365747d3Angus Kong            clear();
1855052117cc429d85cf446421ca74859f4365747d3Angus Kong        }
1865052117cc429d85cf446421ca74859f4365747d3Angus Kong    }
1875052117cc429d85cf446421ca74859f4365747d3Angus Kong
1885052117cc429d85cf446421ca74859f4365747d3Angus Kong    private void clear() {
1895052117cc429d85cf446421ca74859f4365747d3Angus Kong        setVisibility(INVISIBLE);
1905052117cc429d85cf446421ca74859f4365747d3Angus Kong        setImageDrawable(null);
1915052117cc429d85cf446421ca74859f4365747d3Angus Kong    }
1925052117cc429d85cf446421ca74859f4365747d3Angus Kong}
193