BottomBar.java revision 217512ce074220090a8ede01adf0406a70f4958f
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; 59217512ce074220090a8ede01adf0406a70f4958fSpike Sprague private static final int CIRCLE_ANIM_DURATION_MS = 300; 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 106cf9010d314a5a263a3f0e9fa9abf16a80f26d281Spike Sprague private void setPaintColor(int alpha, int color, boolean isCaptureChange) { 107cf9010d314a5a263a3f0e9fa9abf16a80f26d281Spike Sprague int computedColor = (alpha << 24) | (color & 0x00ffffff); 108cf9010d314a5a263a3f0e9fa9abf16a80f26d281Spike Sprague mCirclePaint.setColor(computedColor); 109cf9010d314a5a263a3f0e9fa9abf16a80f26d281Spike Sprague if (!isCaptureChange) { 110cf9010d314a5a263a3f0e9fa9abf16a80f26d281Spike Sprague mOptionsToggle.setBackgroundColor(computedColor); 111cf9010d314a5a263a3f0e9fa9abf16a80f26d281Spike Sprague } 112eaa4d37f8bfb25ffea438f9045867140a63ba0e1Spike Sprague invalidate(); 113b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague } 114b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague 115cf9010d314a5a263a3f0e9fa9abf16a80f26d281Spike Sprague private void setPaintColor(int alpha, int color) { 116cf9010d314a5a263a3f0e9fa9abf16a80f26d281Spike Sprague setPaintColor(alpha, color, false); 117cf9010d314a5a263a3f0e9fa9abf16a80f26d281Spike Sprague } 118cf9010d314a5a263a3f0e9fa9abf16a80f26d281Spike Sprague 1194efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren @Override 1204efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren public void onFinishInflate() { 12156688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren mOptionsOverlay 12256688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren = (TopRightMostOverlay) findViewById(R.id.bottombar_options_overlay); 12356688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren mOptionsLayout 12456688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren = (TopRightWeightedLayout) findViewById(R.id.bottombar_options); 1254efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren mCaptureLayout 1264efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren = (FrameLayout) findViewById(R.id.bottombar_capture); 1274efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren mIntentLayout 1284efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren = (TopRightWeightedLayout) findViewById(R.id.bottombar_intent); 129b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague 13039f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague mShutterButton 13139f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague = (ShutterButton) findViewById(R.id.shutter_button); 132b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague mShutterButton.setOnTouchListener(new OnTouchListener() { 133b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague @Override 134b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague public boolean onTouch(View v, MotionEvent event) { 135b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague if (MotionEvent.ACTION_DOWN == event.getActionMasked()) { 136cf9010d314a5a263a3f0e9fa9abf16a80f26d281Spike Sprague setPaintColor(mBackgroundAlpha, mBackgroundPressedColor, true); 137b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague invalidate(); 138b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague } else if (MotionEvent.ACTION_UP == event.getActionMasked()) { 139cf9010d314a5a263a3f0e9fa9abf16a80f26d281Spike Sprague setPaintColor(mBackgroundAlpha, mBackgroundColor, true); 140b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague invalidate(); 141b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague } 142b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague 143b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague return false; 144b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague } 145b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague }); 14656688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren 14756688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren mOptionsOverlay.setOnTouchListener(new View.OnTouchListener() { 14839f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague @Override 14939f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague public boolean onTouch(View v, MotionEvent event) { 15039f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague if (event.getActionMasked() == MotionEvent.ACTION_DOWN) { 15139f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague // close options immediately. 15239f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague closeModeOptionsDelayed(BOTTOMBAR_OPTIONS_TIMEOUT_MS); 15356688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren } 15439f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague // Let touch event reach mode options or shutter. 15539f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague return false; 15639f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague } 15739f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague }); 15856688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren } 15956688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren 16056688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren @Override 16156688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren public void onPreviewTouched(MotionEvent ev) { 16256688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren // close options immediately. 16356688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren closeModeOptionsDelayed(0); 16456688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren } 16556688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren 16656688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren /** 16756688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren * Schedule (or re-schedule) the options menu to be closed 16856688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren * after a number of milliseconds. If the options menu 16956688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren * is already closed, nothing is scheduled. 17056688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren */ 17156688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren private void closeModeOptionsDelayed(int milliseconds) { 17256688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren // Check that the bottom bar options are visible. 17356688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren if (mOptionsLayout.getVisibility() != View.VISIBLE) { 17456688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren return; 17556688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren } 17656688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren 17756688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren // Remove queued callbacks. 17856688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren removeCallbacks(mCloseOptionsRunnable); 17956688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren 18056688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren // Close the bottom bar options view in n milliseconds. 18156688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren postDelayed(mCloseOptionsRunnable, milliseconds); 1824efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren } 1834efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren 1844efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren /** 1854efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren * Initializes the bottom bar toggle for switching between 18656688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren * capture and the bottom bar options. 1874efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren */ 18856688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren public void setupToggle(boolean isCaptureIntent) { 18956688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren mIsCaptureIntent = isCaptureIntent; 19056688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren 1914efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren // Of type ToggleImageButton because ToggleButton 1924efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren // has a non-removable spacing for text on the right-hand side. 19356688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren mOptionsToggle = (ToggleImageButton) findViewById(R.id.bottombar_options_toggle); 19456688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren mOptionsToggle.setState(0, false); 19556688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren mOptionsToggle.setOnStateChangeListener(new ToggleImageButton.OnStateChangeListener() { 1963b92e2f8e6d91af1b83c8bee95bd93e7153b96daSpike Sprague @Override 19756688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren public void stateChanged(View view, boolean toOptions) { 19856688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren if (toOptions) { 19956688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren if (mIsCaptureIntent) { 2003b92e2f8e6d91af1b83c8bee95bd93e7153b96daSpike Sprague hideIntentLayout(); 2013b92e2f8e6d91af1b83c8bee95bd93e7153b96daSpike Sprague } 20256688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren transitionToOptions(); 2033b92e2f8e6d91af1b83c8bee95bd93e7153b96daSpike Sprague } else { 20456688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren if (mIsCaptureIntent) { 2053b92e2f8e6d91af1b83c8bee95bd93e7153b96daSpike Sprague transitionToIntentLayout(); 2064efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren } else { 2073b92e2f8e6d91af1b83c8bee95bd93e7153b96daSpike Sprague transitionToCapture(); 2084efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren } 2094efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren } 2103b92e2f8e6d91af1b83c8bee95bd93e7153b96daSpike Sprague } 2113b92e2f8e6d91af1b83c8bee95bd93e7153b96daSpike Sprague }); 21256688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren mOptionsOverlay.setReferenceViewParent(mOptionsLayout); 2134efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren } 2144efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren 2154efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren /** 2164efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren * Hide the intent layout. This is necessary for switching between 21756688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren * the intent capture layout and the bottom bar options. 2184efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren */ 2194efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren private void hideIntentLayout() { 2204efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren mIntentLayout.setVisibility(View.INVISIBLE); 2214efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren } 2224efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren 2234efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren /** 22456688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren * Perform a transition from the bottom bar options layout to the 22556688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren * bottom bar capture layout. 2264efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren */ 2274efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren private void transitionToCapture() { 22856688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren mOptionsLayout.setVisibility(View.INVISIBLE); 2294efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren mCaptureLayout.setVisibility(View.VISIBLE); 2304efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren } 2314efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren 2324efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren /** 23356688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren * Perform a transition from the bottom bar capture layout to the 23456688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren * bottom bar options layout. 2354efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren */ 23656688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren private void transitionToOptions() { 2373b92e2f8e6d91af1b83c8bee95bd93e7153b96daSpike Sprague mCaptureLayout.setVisibility(View.INVISIBLE); 23856688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren mOptionsLayout.setVisibility(View.VISIBLE); 2394efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren } 2404efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren 2410744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen /** 2424efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren * Perform a transition to the global intent layout. The current 2434efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren * layout state of the bottom bar is irrelevant. 2440f3c4b4fc9ac87d7d4c3d04c3cb3426c711f57eaSpike Sprague */ 2454efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren public void transitionToIntentLayout() { 2464efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren mCaptureLayout.setVisibility(View.VISIBLE); 24756688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren mOptionsLayout.setVisibility(View.INVISIBLE); 24856688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren mOptionsOverlay.setVisibility(View.VISIBLE); 2494efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren mIntentLayout.setVisibility(View.VISIBLE); 2504efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren 2514efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren View button; 2524efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren button = mIntentLayout.findViewById(R.id.done_button); 2534efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren button.setVisibility(View.INVISIBLE); 2544efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren button = mIntentLayout.findViewById(R.id.retake_button); 2554efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren button.setVisibility(View.INVISIBLE); 2564efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren } 2574efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren 2584efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren /** 2594efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren * Perform a transition to the global intent review layout. 2604efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren * The current layout state of the bottom bar is irrelevant. 2614efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren */ 2624efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren public void transitionToIntentReviewLayout() { 2634efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren mCaptureLayout.setVisibility(View.INVISIBLE); 26456688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren mOptionsLayout.setVisibility(View.INVISIBLE); 26556688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren mOptionsOverlay.setVisibility(View.INVISIBLE); 2664efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren 2674efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren View button; 2684efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren button = mIntentLayout.findViewById(R.id.done_button); 2694efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren button.setVisibility(View.VISIBLE); 2704efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren button = mIntentLayout.findViewById(R.id.retake_button); 2714efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren button.setVisibility(View.VISIBLE); 2724efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren mIntentLayout.setVisibility(View.VISIBLE); 2730f3c4b4fc9ac87d7d4c3d04c3cb3426c711f57eaSpike Sprague } 2740f3c4b4fc9ac87d7d4c3d04c3cb3426c711f57eaSpike Sprague 27570da918464276b110c43868caa272c97baadb89eDoris Liu @Override 27670da918464276b110c43868caa272c97baadb89eDoris Liu public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 27770da918464276b110c43868caa272c97baadb89eDoris Liu mWidth = MeasureSpec.getSize(widthMeasureSpec); 27870da918464276b110c43868caa272c97baadb89eDoris Liu mHeight = MeasureSpec.getSize(heightMeasureSpec); 27970da918464276b110c43868caa272c97baadb89eDoris Liu if (mWidth == 0 || mHeight == 0) { 28070da918464276b110c43868caa272c97baadb89eDoris Liu return; 28170da918464276b110c43868caa272c97baadb89eDoris Liu } 28270da918464276b110c43868caa272c97baadb89eDoris Liu 28370da918464276b110c43868caa272c97baadb89eDoris Liu if (mOffsetShorterEdge != 0 && mOffsetLongerEdge != 0) { 28470da918464276b110c43868caa272c97baadb89eDoris Liu float previewAspectRatio = 28570da918464276b110c43868caa272c97baadb89eDoris Liu mOffsetLongerEdge / mOffsetShorterEdge; 28670da918464276b110c43868caa272c97baadb89eDoris Liu if (previewAspectRatio < 1.0) { 28770da918464276b110c43868caa272c97baadb89eDoris Liu previewAspectRatio = 1.0f/previewAspectRatio; 28870da918464276b110c43868caa272c97baadb89eDoris Liu } 28970da918464276b110c43868caa272c97baadb89eDoris Liu float screenAspectRatio = (float) mWidth / (float) mHeight; 29070da918464276b110c43868caa272c97baadb89eDoris Liu if (screenAspectRatio < 1.0) { 29170da918464276b110c43868caa272c97baadb89eDoris Liu screenAspectRatio = 1.0f/screenAspectRatio; 29270da918464276b110c43868caa272c97baadb89eDoris Liu } 29370da918464276b110c43868caa272c97baadb89eDoris Liu if (previewAspectRatio >= screenAspectRatio) { 29470da918464276b110c43868caa272c97baadb89eDoris Liu mOverLayBottomBar = true; 29539f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague setBackgroundAlpha(128); 29670da918464276b110c43868caa272c97baadb89eDoris Liu } else { 29770da918464276b110c43868caa272c97baadb89eDoris Liu mOverLayBottomBar = false; 29839f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague setBackgroundAlpha(255); 29970da918464276b110c43868caa272c97baadb89eDoris Liu } 30070da918464276b110c43868caa272c97baadb89eDoris Liu } 30170da918464276b110c43868caa272c97baadb89eDoris Liu 30270da918464276b110c43868caa272c97baadb89eDoris Liu // Calculates the width and height needed for the bar. 30370da918464276b110c43868caa272c97baadb89eDoris Liu int barWidth, barHeight; 30470da918464276b110c43868caa272c97baadb89eDoris Liu if (mWidth > mHeight) { 3051648c36927501ff32bf2918e8a445118d5208731Erin Dahlgren // TODO: The bottom bar should not need to care about the 3061648c36927501ff32bf2918e8a445118d5208731Erin Dahlgren // the type of its parent. Handle this in the parent layout. 3071648c36927501ff32bf2918e8a445118d5208731Erin Dahlgren ((LinearLayout.LayoutParams) getLayoutParams()).gravity = Gravity.RIGHT; 30870da918464276b110c43868caa272c97baadb89eDoris Liu if ((mOffsetLongerEdge == 0 && mOffsetShorterEdge == 0) || mOverLayBottomBar) { 30970da918464276b110c43868caa272c97baadb89eDoris Liu barWidth = mOptimalHeight; 31070da918464276b110c43868caa272c97baadb89eDoris Liu barHeight = mHeight; 31170da918464276b110c43868caa272c97baadb89eDoris Liu } else { 31270da918464276b110c43868caa272c97baadb89eDoris Liu barWidth = (int) (mWidth - mOffsetLongerEdge); 31370da918464276b110c43868caa272c97baadb89eDoris Liu barHeight = mHeight; 31470da918464276b110c43868caa272c97baadb89eDoris Liu } 3150744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen } else { 3161648c36927501ff32bf2918e8a445118d5208731Erin Dahlgren ((LinearLayout.LayoutParams) getLayoutParams()).gravity = Gravity.BOTTOM; 31770da918464276b110c43868caa272c97baadb89eDoris Liu if ((mOffsetLongerEdge == 0 && mOffsetShorterEdge == 0) || mOverLayBottomBar) { 31870da918464276b110c43868caa272c97baadb89eDoris Liu barWidth = mWidth; 31970da918464276b110c43868caa272c97baadb89eDoris Liu barHeight = mOptimalHeight; 32070da918464276b110c43868caa272c97baadb89eDoris Liu } else { 32170da918464276b110c43868caa272c97baadb89eDoris Liu barWidth = mWidth; 32270da918464276b110c43868caa272c97baadb89eDoris Liu barHeight = (int) (mHeight - mOffsetLongerEdge); 32370da918464276b110c43868caa272c97baadb89eDoris Liu } 3240744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen } 32539f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague 32639f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague mCirclePath.addCircle( 32739f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague barWidth/2, 32839f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague barHeight/2, 32939f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague (int)(diagonalLength(barWidth, barHeight)/2), 33039f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague Path.Direction.CW); 33139f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague 33270da918464276b110c43868caa272c97baadb89eDoris Liu super.onMeasure(MeasureSpec.makeMeasureSpec(barWidth, MeasureSpec.EXACTLY), 33370da918464276b110c43868caa272c97baadb89eDoris Liu MeasureSpec.makeMeasureSpec(barHeight, MeasureSpec.EXACTLY)); 33470da918464276b110c43868caa272c97baadb89eDoris Liu } 33570da918464276b110c43868caa272c97baadb89eDoris Liu 33670da918464276b110c43868caa272c97baadb89eDoris Liu private void adjustBottomBar(float scaledTextureWidth, 33770da918464276b110c43868caa272c97baadb89eDoris Liu float scaledTextureHeight) { 33870da918464276b110c43868caa272c97baadb89eDoris Liu setOffset(scaledTextureWidth, scaledTextureHeight); 33970da918464276b110c43868caa272c97baadb89eDoris Liu } 34070da918464276b110c43868caa272c97baadb89eDoris Liu 34170da918464276b110c43868caa272c97baadb89eDoris Liu @Override 342a1ec04a9f9526418f5cb17a5afbfc48aca1e02d0Doris Liu public void onPreviewAreaSizeChanged(RectF previewArea) { 343a1ec04a9f9526418f5cb17a5afbfc48aca1e02d0Doris Liu adjustBottomBar(previewArea.width(), previewArea.height()); 34470da918464276b110c43868caa272c97baadb89eDoris Liu } 34570da918464276b110c43868caa272c97baadb89eDoris Liu 34670da918464276b110c43868caa272c97baadb89eDoris Liu private void setOffset(float scaledTextureWidth, float scaledTextureHeight) { 34770da918464276b110c43868caa272c97baadb89eDoris Liu float offsetLongerEdge, offsetShorterEdge; 34870da918464276b110c43868caa272c97baadb89eDoris Liu if (scaledTextureHeight > scaledTextureWidth) { 34970da918464276b110c43868caa272c97baadb89eDoris Liu offsetLongerEdge = scaledTextureHeight; 35070da918464276b110c43868caa272c97baadb89eDoris Liu offsetShorterEdge = scaledTextureWidth; 3510744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen } else { 35270da918464276b110c43868caa272c97baadb89eDoris Liu offsetLongerEdge = scaledTextureWidth; 35370da918464276b110c43868caa272c97baadb89eDoris Liu offsetShorterEdge = scaledTextureHeight; 35470da918464276b110c43868caa272c97baadb89eDoris Liu } 35570da918464276b110c43868caa272c97baadb89eDoris Liu if (mOffsetLongerEdge != offsetLongerEdge || mOffsetShorterEdge != offsetShorterEdge) { 35670da918464276b110c43868caa272c97baadb89eDoris Liu mOffsetLongerEdge = offsetLongerEdge; 35770da918464276b110c43868caa272c97baadb89eDoris Liu mOffsetShorterEdge = offsetShorterEdge; 35870da918464276b110c43868caa272c97baadb89eDoris Liu requestLayout(); 3590744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen } 3600744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen } 3610744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen 3620744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen @Override 3630744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen protected void onConfigurationChanged(Configuration config) { 3640744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen super.onConfigurationChanged(config); 3650744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen } 3660744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen 367e3b0e946924e45f6788db69aaa8f48a2d81031f0Spike Sprague // prevent touches on bottom bar (not its children) 368e3b0e946924e45f6788db69aaa8f48a2d81031f0Spike Sprague // from triggering a touch event on preview area 369e3b0e946924e45f6788db69aaa8f48a2d81031f0Spike Sprague @Override 370e3b0e946924e45f6788db69aaa8f48a2d81031f0Spike Sprague public boolean onTouchEvent(MotionEvent event) { 371e3b0e946924e45f6788db69aaa8f48a2d81031f0Spike Sprague return true; 372e3b0e946924e45f6788db69aaa8f48a2d81031f0Spike Sprague } 37339f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague 37439f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague @Override 37539f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague public void onDraw(Canvas canvas) { 37639f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague canvas.drawPath(mCirclePath, mCirclePaint); 37739f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague 37839f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague super.onDraw(canvas); 37939f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague } 38039f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague 38139f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague @Override 38239f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague public void setBackgroundColor(int color) { 38339f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague mBackgroundColor = color; 384b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague setPaintColor(mBackgroundAlpha, mBackgroundColor); 385b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague } 386b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague 387b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague public void setBackgroundPressedColor(int color) { 388b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague mBackgroundPressedColor = color; 38939f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague } 39039f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague 39139f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague public void setBackgroundAlpha(int alpha) { 392b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague mBackgroundAlpha = alpha; 393b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague setPaintColor(mBackgroundAlpha, mBackgroundColor); 39439f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague } 39539f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague 39639f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague private double diagonalLength(double w, double h) { 39739f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague return Math.sqrt((w*w) + (h*h)); 39839f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague } 39939f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague private double diagonalLength() { 40039f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague return diagonalLength(getWidth(), getHeight()); 40139f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague } 40239f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague 40339f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague private TransitionDrawable crossfadeDrawable(Drawable from, Drawable to) { 40439f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague Drawable [] arrayDrawable = new Drawable[2]; 40539f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague arrayDrawable[0] = from; 40639f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague arrayDrawable[1] = to; 40739f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague TransitionDrawable transitionDrawable = new TransitionDrawable(arrayDrawable); 40839f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague transitionDrawable.setCrossFadeEnabled(true); 40939f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague return transitionDrawable; 41039f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague } 41139f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague 41239f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague /** 41339f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague * Set the shutter button's icon resource 41439f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague */ 41539f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague public void setShutterButtonIcon(int resId) { 41639f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague mShutterButton.setImageResource(resId); 41739f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague } 41839f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague 41939f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague /** 42039f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague * Animates bar to a single stop button 42139f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague */ 42239f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague public void animateToCircle(int resId) { 42339f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague final ValueAnimator radiusAnimator = ValueAnimator.ofFloat( 42439f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague (float) diagonalLength()/2, 42539f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague CIRCLE_RADIUS); 42639f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague radiusAnimator.setDuration(CIRCLE_ANIM_DURATION_MS); 42739f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague radiusAnimator.setInterpolator(Gusterpolator.INSTANCE); 42839f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague 42939f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague radiusAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 43039f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague @Override 43139f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague public void onAnimationUpdate(ValueAnimator animation) { 43239f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague mCirclePath.reset(); 43339f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague mCirclePath.addCircle( 43439f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague getWidth()/2, 43539f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague getHeight()/2, 43639f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague (Float) animation.getAnimatedValue(), 43739f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague Path.Direction.CW); 43839f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague 43939f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague invalidate(); 44039f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague } 44139f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague }); 44239f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague 44339f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague TransitionDrawable transitionDrawable = crossfadeDrawable( 44439f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague mShutterButton.getDrawable(), 44539f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague getResources().getDrawable(resId)); 44639f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague mShutterButton.setImageDrawable(transitionDrawable); 44739f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague 44839f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague View optionsOverlay = findViewById(R.id.bottombar_options_overlay); 44939f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague optionsOverlay.setVisibility(View.INVISIBLE); 45039f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague 45139f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague 45239f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague transitionDrawable.startTransition(CIRCLE_ANIM_DURATION_MS); 45339f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague radiusAnimator.start(); 45439f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague } 45539f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague 45639f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague /** 45739f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague * Animates bar to full width / length with video capture icon 45839f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague */ 45939f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague public void animateToFullSize(int resId) { 46039f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague final ValueAnimator radiusAnimator = ValueAnimator.ofFloat( 46139f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague CIRCLE_RADIUS, 46239f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague (float) diagonalLength()/2); 46339f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague radiusAnimator.setDuration(CIRCLE_ANIM_DURATION_MS); 46439f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague radiusAnimator.setInterpolator(Gusterpolator.INSTANCE); 46539f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague radiusAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 46639f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague @Override 46739f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague public void onAnimationUpdate(ValueAnimator animation) { 46839f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague mCirclePath.reset(); 46939f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague mCirclePath.addCircle( 47039f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague getWidth()/2, 47139f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague getHeight()/2, 47239f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague (Float) animation.getAnimatedValue(), 47339f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague Path.Direction.CW); 47439f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague 47539f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague invalidate(); 47639f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague } 47739f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague }); 47839f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague radiusAnimator.addListener(new AnimatorListenerAdapter() { 47939f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague @Override 48039f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague public void onAnimationEnd(Animator animation) { 48139f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague View optionsOverlay = findViewById(R.id.bottombar_options_overlay); 48239f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague optionsOverlay.setVisibility(View.VISIBLE); 48339f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague } 48439f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague }); 48539f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague 48639f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague TransitionDrawable transitionDrawable = crossfadeDrawable( 48739f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague mShutterButton.getDrawable(), 48839f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague getResources().getDrawable(resId)); 48939f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague mShutterButton.setImageDrawable(transitionDrawable); 49039f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague 49139f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague transitionDrawable.startTransition(CIRCLE_ANIM_DURATION_MS); 49239f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague radiusAnimator.start(); 49339f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague } 4940744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen} 495