BottomBar.java revision a1ec04a9f9526418f5cb17a5afbfc48aca1e02d0
10744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen/*
20744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen * Copyright (C) 2013 The Android Open Source Project
30744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen *
40744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen * Licensed under the Apache License, Version 2.0 (the "License");
50744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen * you may not use this file except in compliance with the License.
60744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen * You may obtain a copy of the License at
70744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen *
80744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen *      http://www.apache.org/licenses/LICENSE-2.0
90744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen *
100744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen * Unless required by applicable law or agreed to in writing, software
110744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen * distributed under the License is distributed on an "AS IS" BASIS,
120744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen * See the License for the specific language governing permissions and
140744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen * limitations under the License.
150744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen */
160744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen
170744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissenpackage com.android.camera.ui;
180744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen
1939f8a7647aa4051a1c260b9496c2db82f93f8667Spike Spragueimport android.animation.Animator;
2039f8a7647aa4051a1c260b9496c2db82f93f8667Spike Spragueimport android.animation.AnimatorListenerAdapter;
2139f8a7647aa4051a1c260b9496c2db82f93f8667Spike Spragueimport android.animation.ValueAnimator;
220744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissenimport android.content.Context;
230744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissenimport android.content.res.Configuration;
24a1ec04a9f9526418f5cb17a5afbfc48aca1e02d0Doris Liuimport android.graphics.RectF;
250744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissenimport android.util.AttributeSet;
260744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissenimport android.view.Gravity;
274efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgrenimport android.view.MotionEvent;
280744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissenimport android.view.View;
290744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissenimport android.widget.FrameLayout;
301648c36927501ff32bf2918e8a445118d5208731Erin Dahlgrenimport android.widget.LinearLayout;
310744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen
3239f8a7647aa4051a1c260b9496c2db82f93f8667Spike Spragueimport com.android.camera.ShutterButton;
334efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgrenimport com.android.camera.ToggleImageButton;
3439f8a7647aa4051a1c260b9496c2db82f93f8667Spike Spragueimport com.android.camera.util.Gusterpolator;
3539f8a7647aa4051a1c260b9496c2db82f93f8667Spike Spragueimport com.android.camera2.R;
3639f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague
3739f8a7647aa4051a1c260b9496c2db82f93f8667Spike Spragueimport android.graphics.Canvas;
3839f8a7647aa4051a1c260b9496c2db82f93f8667Spike Spragueimport android.graphics.Path;
3939f8a7647aa4051a1c260b9496c2db82f93f8667Spike Spragueimport android.graphics.Paint;
4039f8a7647aa4051a1c260b9496c2db82f93f8667Spike Spragueimport android.graphics.drawable.Drawable;
4139f8a7647aa4051a1c260b9496c2db82f93f8667Spike Spragueimport android.graphics.drawable.TransitionDrawable;
4270da918464276b110c43868caa272c97baadb89eDoris Liu
430744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen/**
440744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen * BottomBar swaps its width and height on rotation. In addition, it also changes
450744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen * gravity and layout orientation based on the new orientation. Specifically, in
460744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen * landscape it aligns to the right side of its parent and lays out its children
470744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen * vertically, whereas in portrait, it stays at the bottom of the parent and has
480744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen * a horizontal layout orientation.
4939f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague*/
5070da918464276b110c43868caa272c97baadb89eDoris Liupublic class BottomBar extends FrameLayout
5156688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren    implements PreviewStatusListener.PreviewAreaSizeChangedListener,
5256688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren               PreviewOverlay.OnPreviewTouchedListener {
533b92e2f8e6d91af1b83c8bee95bd93e7153b96daSpike Sprague
5470da918464276b110c43868caa272c97baadb89eDoris Liu    private static final String TAG = "BottomBar";
5539f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague
5656688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren    private static final int BOTTOMBAR_OPTIONS_TIMEOUT_MS = 2000;
5756688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren
5839f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague    private static final float CIRCLE_RADIUS = 64.0f;
5939f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague    private static final int CIRCLE_ANIM_DURATION_MS = 450;
6039f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague
6170da918464276b110c43868caa272c97baadb89eDoris Liu    private int mWidth;
6270da918464276b110c43868caa272c97baadb89eDoris Liu    private int mHeight;
6370da918464276b110c43868caa272c97baadb89eDoris Liu    private float mOffsetShorterEdge;
6470da918464276b110c43868caa272c97baadb89eDoris Liu    private float mOffsetLongerEdge;
6570da918464276b110c43868caa272c97baadb89eDoris Liu
6670da918464276b110c43868caa272c97baadb89eDoris Liu    private final int mOptimalHeight;
6770da918464276b110c43868caa272c97baadb89eDoris Liu    private boolean mOverLayBottomBar;
680744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen
6956688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren    private ToggleImageButton mOptionsToggle;
7056688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren
7156688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren    private TopRightMostOverlay mOptionsOverlay;
7256688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren    private TopRightWeightedLayout mOptionsLayout;
734efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren    private FrameLayout mCaptureLayout;
744efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren    private TopRightWeightedLayout mIntentLayout;
7556688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren    private boolean mIsCaptureIntent = false;
7656688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren
7756688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren    /**
7856688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren     * A generic Runnable for setting the options toggle
7956688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren     * to the capture layout state and performing the state
8056688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren     * transition.
8156688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren     */
8256688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren    private final Runnable mCloseOptionsRunnable =
8356688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren        new Runnable() {
8456688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren            @Override
8556688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren            public void run() {
8656688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren                if (mOptionsToggle != null) {
8756688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren                    mOptionsToggle.setState(0, true);
8856688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren                }
8956688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren            }
9056688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren        };
914efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren
9239f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague    private ShutterButton mShutterButton;
9339f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague
9439f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague    private int mBackgroundColor;
95b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague    private int mBackgroundPressedColor;
96b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague    private int mBackgroundAlpha = 0xff;
97b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague
9839f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague    private Paint mCirclePaint = new Paint();
9939f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague    private Path mCirclePath = new Path();
10039f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague
1010744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen    public BottomBar(Context context, AttributeSet attrs) {
1020744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen        super(context, attrs);
10370da918464276b110c43868caa272c97baadb89eDoris Liu        mOptimalHeight = getResources().getDimensionPixelSize(R.dimen.bottom_bar_height_optimal);
1040744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen    }
1050744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen
106b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague    private void setPaintColor(int alpha, int color) {
107b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague        mCirclePaint.setColor((alpha << 24) | (color & 0x00ffffff));
108b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague    }
109b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague
1104efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren    @Override
1114efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren    public void onFinishInflate() {
11256688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren        mOptionsOverlay
11356688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren            = (TopRightMostOverlay) findViewById(R.id.bottombar_options_overlay);
11456688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren        mOptionsLayout
11556688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren            = (TopRightWeightedLayout) findViewById(R.id.bottombar_options);
1164efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren        mCaptureLayout
1174efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren            = (FrameLayout) findViewById(R.id.bottombar_capture);
1184efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren        mIntentLayout
1194efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren            = (TopRightWeightedLayout) findViewById(R.id.bottombar_intent);
120b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague
12139f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague        mShutterButton
12239f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague            = (ShutterButton) findViewById(R.id.shutter_button);
123b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague        mShutterButton.setOnTouchListener(new OnTouchListener() {
124b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague            @Override
125b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague            public boolean onTouch(View v, MotionEvent event) {
126b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague                if (MotionEvent.ACTION_DOWN == event.getActionMasked()) {
127b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague                    setPaintColor(mBackgroundAlpha, mBackgroundPressedColor);
128b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague                    invalidate();
129b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague                } else if (MotionEvent.ACTION_UP == event.getActionMasked()) {
130b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague                    setPaintColor(mBackgroundAlpha, mBackgroundColor);
131b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague                    invalidate();
132b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague                }
133b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague
134b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague                return false;
135b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague            }
136b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague        });
13756688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren
13856688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren        mOptionsOverlay.setOnTouchListener(new View.OnTouchListener() {
13939f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague            @Override
14039f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague            public boolean onTouch(View v, MotionEvent event) {
14139f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague                if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
14239f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague                    // close options immediately.
14339f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague                    closeModeOptionsDelayed(BOTTOMBAR_OPTIONS_TIMEOUT_MS);
14456688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren                }
14539f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague                // Let touch event reach mode options or shutter.
14639f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague                return false;
14739f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague            }
14839f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague        });
14956688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren    }
15056688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren
15156688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren    @Override
15256688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren    public void onPreviewTouched(MotionEvent ev) {
15356688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren        // close options immediately.
15456688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren        closeModeOptionsDelayed(0);
15556688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren    }
15656688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren
15756688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren    /**
15856688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren     * Schedule (or re-schedule) the options menu to be closed
15956688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren     * after a number of milliseconds.  If the options menu
16056688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren     * is already closed, nothing is scheduled.
16156688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren     */
16256688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren    private void closeModeOptionsDelayed(int milliseconds) {
16356688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren        // Check that the bottom bar options are visible.
16456688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren        if (mOptionsLayout.getVisibility() != View.VISIBLE) {
16556688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren            return;
16656688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren        }
16756688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren
16856688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren        // Remove queued callbacks.
16956688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren        removeCallbacks(mCloseOptionsRunnable);
17056688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren
17156688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren        // Close the bottom bar options view in n milliseconds.
17256688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren        postDelayed(mCloseOptionsRunnable, milliseconds);
1734efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren    }
1744efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren
1754efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren    /**
1764efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren     * Initializes the bottom bar toggle for switching between
17756688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren     * capture and the bottom bar options.
1784efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren     */
17956688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren    public void setupToggle(boolean isCaptureIntent) {
18056688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren        mIsCaptureIntent = isCaptureIntent;
18156688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren
1824efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren        // Of type ToggleImageButton because ToggleButton
1834efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren        // has a non-removable spacing for text on the right-hand side.
18456688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren        mOptionsToggle = (ToggleImageButton) findViewById(R.id.bottombar_options_toggle);
18556688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren        mOptionsToggle.setState(0, false);
18656688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren        mOptionsToggle.setOnStateChangeListener(new ToggleImageButton.OnStateChangeListener() {
1873b92e2f8e6d91af1b83c8bee95bd93e7153b96daSpike Sprague            @Override
18856688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren            public void stateChanged(View view, boolean toOptions) {
18956688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren                if (toOptions) {
19056688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren                    if (mIsCaptureIntent) {
1913b92e2f8e6d91af1b83c8bee95bd93e7153b96daSpike Sprague                        hideIntentLayout();
1923b92e2f8e6d91af1b83c8bee95bd93e7153b96daSpike Sprague                    }
19356688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren                    transitionToOptions();
1943b92e2f8e6d91af1b83c8bee95bd93e7153b96daSpike Sprague                } else {
19556688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren                    if (mIsCaptureIntent) {
1963b92e2f8e6d91af1b83c8bee95bd93e7153b96daSpike Sprague                        transitionToIntentLayout();
1974efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren                    } else {
1983b92e2f8e6d91af1b83c8bee95bd93e7153b96daSpike Sprague                        transitionToCapture();
1994efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren                    }
2004efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren                }
2013b92e2f8e6d91af1b83c8bee95bd93e7153b96daSpike Sprague            }
2023b92e2f8e6d91af1b83c8bee95bd93e7153b96daSpike Sprague        });
20356688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren        mOptionsOverlay.setReferenceViewParent(mOptionsLayout);
2044efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren    }
2054efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren
2064efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren    /**
2074efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren     * Hide the intent layout.  This is necessary for switching between
20856688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren     * the intent capture layout and the bottom bar options.
2094efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren     */
2104efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren    private void hideIntentLayout() {
2114efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren        mIntentLayout.setVisibility(View.INVISIBLE);
2124efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren    }
2134efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren
2144efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren    /**
21556688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren     * Perform a transition from the bottom bar options layout to the
21656688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren     * bottom bar capture layout.
2174efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren     */
2184efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren    private void transitionToCapture() {
21956688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren        mOptionsLayout.setVisibility(View.INVISIBLE);
2204efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren        mCaptureLayout.setVisibility(View.VISIBLE);
2214efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren    }
2224efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren
2234efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren    /**
22456688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren     * Perform a transition from the bottom bar capture layout to the
22556688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren     * bottom bar options layout.
2264efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren     */
22756688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren    private void transitionToOptions() {
2283b92e2f8e6d91af1b83c8bee95bd93e7153b96daSpike Sprague        mCaptureLayout.setVisibility(View.INVISIBLE);
22956688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren        mOptionsLayout.setVisibility(View.VISIBLE);
2304efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren    }
2314efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren
2320744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen    /**
2334efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren     * Perform a transition to the global intent layout.  The current
2344efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren     * layout state of the bottom bar is irrelevant.
2350f3c4b4fc9ac87d7d4c3d04c3cb3426c711f57eaSpike Sprague     */
2364efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren    public void transitionToIntentLayout() {
2374efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren        mCaptureLayout.setVisibility(View.VISIBLE);
23856688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren        mOptionsLayout.setVisibility(View.INVISIBLE);
23956688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren        mOptionsOverlay.setVisibility(View.VISIBLE);
2404efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren        mIntentLayout.setVisibility(View.VISIBLE);
2414efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren
2424efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren        View button;
2434efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren        button = mIntentLayout.findViewById(R.id.done_button);
2444efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren        button.setVisibility(View.INVISIBLE);
2454efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren        button = mIntentLayout.findViewById(R.id.retake_button);
2464efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren        button.setVisibility(View.INVISIBLE);
2474efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren    }
2484efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren
2494efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren    /**
2504efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren     * Perform a transition to the global intent review layout.
2514efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren     * The current layout state of the bottom bar is irrelevant.
2524efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren     */
2534efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren    public void transitionToIntentReviewLayout() {
2544efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren        mCaptureLayout.setVisibility(View.INVISIBLE);
25556688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren        mOptionsLayout.setVisibility(View.INVISIBLE);
25656688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren        mOptionsOverlay.setVisibility(View.INVISIBLE);
2574efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren
2584efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren        View button;
2594efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren        button = mIntentLayout.findViewById(R.id.done_button);
2604efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren        button.setVisibility(View.VISIBLE);
2614efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren        button = mIntentLayout.findViewById(R.id.retake_button);
2624efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren        button.setVisibility(View.VISIBLE);
2634efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren        mIntentLayout.setVisibility(View.VISIBLE);
2640f3c4b4fc9ac87d7d4c3d04c3cb3426c711f57eaSpike Sprague    }
2650f3c4b4fc9ac87d7d4c3d04c3cb3426c711f57eaSpike Sprague
26670da918464276b110c43868caa272c97baadb89eDoris Liu    @Override
26770da918464276b110c43868caa272c97baadb89eDoris Liu    public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
26870da918464276b110c43868caa272c97baadb89eDoris Liu        mWidth = MeasureSpec.getSize(widthMeasureSpec);
26970da918464276b110c43868caa272c97baadb89eDoris Liu        mHeight = MeasureSpec.getSize(heightMeasureSpec);
27070da918464276b110c43868caa272c97baadb89eDoris Liu        if (mWidth == 0 || mHeight == 0) {
27170da918464276b110c43868caa272c97baadb89eDoris Liu            return;
27270da918464276b110c43868caa272c97baadb89eDoris Liu        }
27370da918464276b110c43868caa272c97baadb89eDoris Liu
27470da918464276b110c43868caa272c97baadb89eDoris Liu        if (mOffsetShorterEdge != 0 && mOffsetLongerEdge != 0) {
27570da918464276b110c43868caa272c97baadb89eDoris Liu            float previewAspectRatio =
27670da918464276b110c43868caa272c97baadb89eDoris Liu                    mOffsetLongerEdge / mOffsetShorterEdge;
27770da918464276b110c43868caa272c97baadb89eDoris Liu            if (previewAspectRatio < 1.0) {
27870da918464276b110c43868caa272c97baadb89eDoris Liu                previewAspectRatio = 1.0f/previewAspectRatio;
27970da918464276b110c43868caa272c97baadb89eDoris Liu            }
28070da918464276b110c43868caa272c97baadb89eDoris Liu            float screenAspectRatio = (float) mWidth / (float) mHeight;
28170da918464276b110c43868caa272c97baadb89eDoris Liu            if (screenAspectRatio < 1.0) {
28270da918464276b110c43868caa272c97baadb89eDoris Liu                screenAspectRatio = 1.0f/screenAspectRatio;
28370da918464276b110c43868caa272c97baadb89eDoris Liu            }
28470da918464276b110c43868caa272c97baadb89eDoris Liu            if (previewAspectRatio >= screenAspectRatio) {
28570da918464276b110c43868caa272c97baadb89eDoris Liu                mOverLayBottomBar = true;
28639f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague                setBackgroundAlpha(128);
28770da918464276b110c43868caa272c97baadb89eDoris Liu            } else {
28870da918464276b110c43868caa272c97baadb89eDoris Liu                mOverLayBottomBar = false;
28939f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague                setBackgroundAlpha(255);
29070da918464276b110c43868caa272c97baadb89eDoris Liu            }
29170da918464276b110c43868caa272c97baadb89eDoris Liu        }
29270da918464276b110c43868caa272c97baadb89eDoris Liu
29370da918464276b110c43868caa272c97baadb89eDoris Liu        // Calculates the width and height needed for the bar.
29470da918464276b110c43868caa272c97baadb89eDoris Liu        int barWidth, barHeight;
29570da918464276b110c43868caa272c97baadb89eDoris Liu        if (mWidth > mHeight) {
2961648c36927501ff32bf2918e8a445118d5208731Erin Dahlgren            // TODO: The bottom bar should not need to care about the
2971648c36927501ff32bf2918e8a445118d5208731Erin Dahlgren            // the type of its parent.  Handle this in the parent layout.
2981648c36927501ff32bf2918e8a445118d5208731Erin Dahlgren            ((LinearLayout.LayoutParams) getLayoutParams()).gravity = Gravity.RIGHT;
29970da918464276b110c43868caa272c97baadb89eDoris Liu            if ((mOffsetLongerEdge == 0 && mOffsetShorterEdge == 0) || mOverLayBottomBar) {
30070da918464276b110c43868caa272c97baadb89eDoris Liu                barWidth = mOptimalHeight;
30170da918464276b110c43868caa272c97baadb89eDoris Liu                barHeight = mHeight;
30270da918464276b110c43868caa272c97baadb89eDoris Liu            } else {
30370da918464276b110c43868caa272c97baadb89eDoris Liu                barWidth = (int) (mWidth - mOffsetLongerEdge);
30470da918464276b110c43868caa272c97baadb89eDoris Liu                barHeight = mHeight;
30570da918464276b110c43868caa272c97baadb89eDoris Liu            }
3060744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen        } else {
3071648c36927501ff32bf2918e8a445118d5208731Erin Dahlgren            ((LinearLayout.LayoutParams) getLayoutParams()).gravity = Gravity.BOTTOM;
30870da918464276b110c43868caa272c97baadb89eDoris Liu            if ((mOffsetLongerEdge == 0 && mOffsetShorterEdge == 0) || mOverLayBottomBar) {
30970da918464276b110c43868caa272c97baadb89eDoris Liu                barWidth = mWidth;
31070da918464276b110c43868caa272c97baadb89eDoris Liu                barHeight = mOptimalHeight;
31170da918464276b110c43868caa272c97baadb89eDoris Liu            } else {
31270da918464276b110c43868caa272c97baadb89eDoris Liu                barWidth = mWidth;
31370da918464276b110c43868caa272c97baadb89eDoris Liu                barHeight = (int) (mHeight - mOffsetLongerEdge);
31470da918464276b110c43868caa272c97baadb89eDoris Liu            }
3150744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen        }
31639f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague
31739f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague        mCirclePath.addCircle(
31839f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague            barWidth/2,
31939f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague            barHeight/2,
32039f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague            (int)(diagonalLength(barWidth, barHeight)/2),
32139f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague            Path.Direction.CW);
32239f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague
32370da918464276b110c43868caa272c97baadb89eDoris Liu        super.onMeasure(MeasureSpec.makeMeasureSpec(barWidth, MeasureSpec.EXACTLY),
32470da918464276b110c43868caa272c97baadb89eDoris Liu                MeasureSpec.makeMeasureSpec(barHeight, MeasureSpec.EXACTLY));
32570da918464276b110c43868caa272c97baadb89eDoris Liu    }
32670da918464276b110c43868caa272c97baadb89eDoris Liu
32770da918464276b110c43868caa272c97baadb89eDoris Liu    private void adjustBottomBar(float scaledTextureWidth,
32870da918464276b110c43868caa272c97baadb89eDoris Liu                                 float scaledTextureHeight) {
32970da918464276b110c43868caa272c97baadb89eDoris Liu        setOffset(scaledTextureWidth, scaledTextureHeight);
33070da918464276b110c43868caa272c97baadb89eDoris Liu    }
33170da918464276b110c43868caa272c97baadb89eDoris Liu
33270da918464276b110c43868caa272c97baadb89eDoris Liu    @Override
333a1ec04a9f9526418f5cb17a5afbfc48aca1e02d0Doris Liu    public void onPreviewAreaSizeChanged(RectF previewArea) {
334a1ec04a9f9526418f5cb17a5afbfc48aca1e02d0Doris Liu        adjustBottomBar(previewArea.width(), previewArea.height());
33570da918464276b110c43868caa272c97baadb89eDoris Liu    }
33670da918464276b110c43868caa272c97baadb89eDoris Liu
33770da918464276b110c43868caa272c97baadb89eDoris Liu    private void setOffset(float scaledTextureWidth, float scaledTextureHeight) {
33870da918464276b110c43868caa272c97baadb89eDoris Liu        float offsetLongerEdge, offsetShorterEdge;
33970da918464276b110c43868caa272c97baadb89eDoris Liu        if (scaledTextureHeight > scaledTextureWidth) {
34070da918464276b110c43868caa272c97baadb89eDoris Liu            offsetLongerEdge = scaledTextureHeight;
34170da918464276b110c43868caa272c97baadb89eDoris Liu            offsetShorterEdge = scaledTextureWidth;
3420744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen        } else {
34370da918464276b110c43868caa272c97baadb89eDoris Liu            offsetLongerEdge = scaledTextureWidth;
34470da918464276b110c43868caa272c97baadb89eDoris Liu            offsetShorterEdge = scaledTextureHeight;
34570da918464276b110c43868caa272c97baadb89eDoris Liu        }
34670da918464276b110c43868caa272c97baadb89eDoris Liu        if (mOffsetLongerEdge != offsetLongerEdge || mOffsetShorterEdge != offsetShorterEdge) {
34770da918464276b110c43868caa272c97baadb89eDoris Liu            mOffsetLongerEdge = offsetLongerEdge;
34870da918464276b110c43868caa272c97baadb89eDoris Liu            mOffsetShorterEdge = offsetShorterEdge;
34970da918464276b110c43868caa272c97baadb89eDoris Liu            requestLayout();
3500744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen        }
3510744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen    }
3520744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen
3530744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen    @Override
3540744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen    protected void onConfigurationChanged(Configuration config) {
3550744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen        super.onConfigurationChanged(config);
3560744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen    }
3570744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen
358e3b0e946924e45f6788db69aaa8f48a2d81031f0Spike Sprague    // prevent touches on bottom bar (not its children)
359e3b0e946924e45f6788db69aaa8f48a2d81031f0Spike Sprague    // from triggering a touch event on preview area
360e3b0e946924e45f6788db69aaa8f48a2d81031f0Spike Sprague    @Override
361e3b0e946924e45f6788db69aaa8f48a2d81031f0Spike Sprague    public boolean onTouchEvent(MotionEvent event) {
362e3b0e946924e45f6788db69aaa8f48a2d81031f0Spike Sprague        return true;
363e3b0e946924e45f6788db69aaa8f48a2d81031f0Spike Sprague    }
36439f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague
36539f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague    @Override
36639f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague    public void onDraw(Canvas canvas) {
36739f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague        canvas.drawPath(mCirclePath, mCirclePaint);
36839f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague
36939f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague        super.onDraw(canvas);
37039f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague    }
37139f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague
37239f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague    @Override
37339f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague    public void setBackgroundColor(int color) {
37439f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague        mBackgroundColor = color;
375b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague        setPaintColor(mBackgroundAlpha, mBackgroundColor);
376b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague    }
377b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague
378b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague    public void setBackgroundPressedColor(int color) {
379b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague        mBackgroundPressedColor = color;
38039f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague    }
38139f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague
38239f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague    public void setBackgroundAlpha(int alpha) {
383b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague        mBackgroundAlpha = alpha;
384b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague        setPaintColor(mBackgroundAlpha, mBackgroundColor);
38539f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague    }
38639f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague
38739f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague    private double diagonalLength(double w, double h) {
38839f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague        return Math.sqrt((w*w) + (h*h));
38939f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague    }
39039f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague    private double diagonalLength() {
39139f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague        return diagonalLength(getWidth(), getHeight());
39239f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague    }
39339f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague
39439f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague    private TransitionDrawable crossfadeDrawable(Drawable from, Drawable to) {
39539f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague        Drawable [] arrayDrawable = new Drawable[2];
39639f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague        arrayDrawable[0] = from;
39739f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague        arrayDrawable[1] = to;
39839f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague        TransitionDrawable transitionDrawable = new TransitionDrawable(arrayDrawable);
39939f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague        transitionDrawable.setCrossFadeEnabled(true);
40039f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague        return transitionDrawable;
40139f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague    }
40239f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague
40339f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague    /**
40439f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague     * Set the shutter button's icon resource
40539f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague     */
40639f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague    public void setShutterButtonIcon(int resId) {
40739f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague        mShutterButton.setImageResource(resId);
40839f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague    }
40939f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague
41039f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague    /**
41139f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague     * Animates bar to a single stop button
41239f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague     */
41339f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague    public void animateToCircle(int resId) {
41439f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague        final ValueAnimator radiusAnimator = ValueAnimator.ofFloat(
41539f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague                                                 (float) diagonalLength()/2,
41639f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague                                                 CIRCLE_RADIUS);
41739f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague        radiusAnimator.setDuration(CIRCLE_ANIM_DURATION_MS);
41839f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague        radiusAnimator.setInterpolator(Gusterpolator.INSTANCE);
41939f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague
42039f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague        radiusAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
42139f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague            @Override
42239f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague            public void onAnimationUpdate(ValueAnimator animation) {
42339f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague                mCirclePath.reset();
42439f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague                mCirclePath.addCircle(
42539f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague                    getWidth()/2,
42639f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague                    getHeight()/2,
42739f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague                    (Float) animation.getAnimatedValue(),
42839f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague                    Path.Direction.CW);
42939f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague
43039f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague                invalidate();
43139f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague            }
43239f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague        });
43339f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague
43439f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague        TransitionDrawable transitionDrawable = crossfadeDrawable(
43539f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague                mShutterButton.getDrawable(),
43639f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague                getResources().getDrawable(resId));
43739f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague        mShutterButton.setImageDrawable(transitionDrawable);
43839f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague
43939f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague        View optionsOverlay = findViewById(R.id.bottombar_options_overlay);
44039f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague        optionsOverlay.setVisibility(View.INVISIBLE);
44139f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague
44239f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague
44339f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague        transitionDrawable.startTransition(CIRCLE_ANIM_DURATION_MS);
44439f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague        radiusAnimator.start();
44539f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague    }
44639f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague
44739f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague    /**
44839f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague     * Animates bar to full width / length with video capture icon
44939f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague     */
45039f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague    public void animateToFullSize(int resId) {
45139f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague        final ValueAnimator radiusAnimator = ValueAnimator.ofFloat(
45239f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague                                                 CIRCLE_RADIUS,
45339f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague                                                 (float) diagonalLength()/2);
45439f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague        radiusAnimator.setDuration(CIRCLE_ANIM_DURATION_MS);
45539f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague        radiusAnimator.setInterpolator(Gusterpolator.INSTANCE);
45639f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague        radiusAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
45739f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague            @Override
45839f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague            public void onAnimationUpdate(ValueAnimator animation) {
45939f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague                mCirclePath.reset();
46039f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague                mCirclePath.addCircle(
46139f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague                    getWidth()/2,
46239f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague                    getHeight()/2,
46339f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague                    (Float) animation.getAnimatedValue(),
46439f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague                    Path.Direction.CW);
46539f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague
46639f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague                invalidate();
46739f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague            }
46839f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague        });
46939f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague        radiusAnimator.addListener(new AnimatorListenerAdapter() {
47039f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague            @Override
47139f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague            public void onAnimationEnd(Animator animation) {
47239f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague                View optionsOverlay = findViewById(R.id.bottombar_options_overlay);
47339f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague                optionsOverlay.setVisibility(View.VISIBLE);
47439f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague            }
47539f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague        });
47639f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague
47739f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague        TransitionDrawable transitionDrawable = crossfadeDrawable(
47839f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague                mShutterButton.getDrawable(),
47939f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague                getResources().getDrawable(resId));
48039f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague        mShutterButton.setImageDrawable(transitionDrawable);
48139f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague
48239f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague        transitionDrawable.startTransition(CIRCLE_ANIM_DURATION_MS);
48339f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague        radiusAnimator.start();
48439f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague    }
4850744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen}
486