BottomBar.java revision b92910e04c4da91fc4ea5a9484b83f9ecba1c896
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; 2239f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague 230744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissenimport android.content.Context; 240744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissenimport android.content.res.Configuration; 2556688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgrenimport android.os.Handler; 2656688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgrenimport android.os.HandlerThread; 2756688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgrenimport android.os.Looper; 280744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissenimport android.util.AttributeSet; 290744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissenimport android.view.Gravity; 304efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgrenimport android.view.MotionEvent; 310744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissenimport android.view.View; 323b92e2f8e6d91af1b83c8bee95bd93e7153b96daSpike Spragueimport android.view.ViewGroup; 330744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissenimport android.widget.FrameLayout; 341648c36927501ff32bf2918e8a445118d5208731Erin Dahlgrenimport android.widget.LinearLayout; 350744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen 3639f8a7647aa4051a1c260b9496c2db82f93f8667Spike Spragueimport com.android.camera.ShutterButton; 374efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgrenimport com.android.camera.ToggleImageButton; 3839f8a7647aa4051a1c260b9496c2db82f93f8667Spike Spragueimport com.android.camera.util.Gusterpolator; 3939f8a7647aa4051a1c260b9496c2db82f93f8667Spike Spragueimport com.android.camera2.R; 4039f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague 4139f8a7647aa4051a1c260b9496c2db82f93f8667Spike Spragueimport android.graphics.Canvas; 4239f8a7647aa4051a1c260b9496c2db82f93f8667Spike Spragueimport android.graphics.Path; 4339f8a7647aa4051a1c260b9496c2db82f93f8667Spike Spragueimport android.graphics.Paint; 4439f8a7647aa4051a1c260b9496c2db82f93f8667Spike Spragueimport android.graphics.drawable.Drawable; 4539f8a7647aa4051a1c260b9496c2db82f93f8667Spike Spragueimport android.graphics.drawable.TransitionDrawable; 4670da918464276b110c43868caa272c97baadb89eDoris Liu 470744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen/** 480744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen * BottomBar swaps its width and height on rotation. In addition, it also changes 490744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen * gravity and layout orientation based on the new orientation. Specifically, in 500744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen * landscape it aligns to the right side of its parent and lays out its children 510744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen * vertically, whereas in portrait, it stays at the bottom of the parent and has 520744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen * a horizontal layout orientation. 5339f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague*/ 5470da918464276b110c43868caa272c97baadb89eDoris Liupublic class BottomBar extends FrameLayout 5556688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren implements PreviewStatusListener.PreviewAreaSizeChangedListener, 5656688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren PreviewOverlay.OnPreviewTouchedListener { 573b92e2f8e6d91af1b83c8bee95bd93e7153b96daSpike Sprague 5870da918464276b110c43868caa272c97baadb89eDoris Liu private static final String TAG = "BottomBar"; 5939f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague 6056688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren private static final int BOTTOMBAR_OPTIONS_TIMEOUT_MS = 2000; 6156688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren 6239f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague private static final float CIRCLE_RADIUS = 64.0f; 6339f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague private static final int CIRCLE_ANIM_DURATION_MS = 450; 6439f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague 6570da918464276b110c43868caa272c97baadb89eDoris Liu private int mWidth; 6670da918464276b110c43868caa272c97baadb89eDoris Liu private int mHeight; 6770da918464276b110c43868caa272c97baadb89eDoris Liu private float mOffsetShorterEdge; 6870da918464276b110c43868caa272c97baadb89eDoris Liu private float mOffsetLongerEdge; 6970da918464276b110c43868caa272c97baadb89eDoris Liu 7070da918464276b110c43868caa272c97baadb89eDoris Liu private final int mOptimalHeight; 7170da918464276b110c43868caa272c97baadb89eDoris Liu private boolean mOverLayBottomBar; 720744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen 7356688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren private ToggleImageButton mOptionsToggle; 7456688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren 7556688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren private TopRightMostOverlay mOptionsOverlay; 7656688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren private TopRightWeightedLayout mOptionsLayout; 774efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren private FrameLayout mCaptureLayout; 784efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren private TopRightWeightedLayout mIntentLayout; 7956688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren private boolean mIsCaptureIntent = false; 8056688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren 8156688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren /** 8256688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren * A generic Runnable for setting the options toggle 8356688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren * to the capture layout state and performing the state 8456688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren * transition. 8556688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren */ 8656688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren private final Runnable mCloseOptionsRunnable = 8756688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren new Runnable() { 8856688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren @Override 8956688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren public void run() { 9056688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren if (mOptionsToggle != null) { 9156688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren mOptionsToggle.setState(0, true); 9256688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren } 9356688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren } 9456688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren }; 954efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren 9639f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague private ShutterButton mShutterButton; 9739f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague 9839f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague private int mBackgroundColor; 99b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague private int mBackgroundPressedColor; 100b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague private int mBackgroundAlpha = 0xff; 101b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague 10239f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague private Paint mCirclePaint = new Paint(); 10339f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague private Path mCirclePath = new Path(); 10439f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague 1050744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen public BottomBar(Context context, AttributeSet attrs) { 1060744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen super(context, attrs); 10770da918464276b110c43868caa272c97baadb89eDoris Liu mOptimalHeight = getResources().getDimensionPixelSize(R.dimen.bottom_bar_height_optimal); 1080744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen } 1090744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen 110b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague private void setPaintColor(int alpha, int color) { 111b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague mCirclePaint.setColor((alpha << 24) | (color & 0x00ffffff)); 112b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague } 113b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague 1144efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren @Override 1154efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren public void onFinishInflate() { 11656688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren mOptionsOverlay 11756688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren = (TopRightMostOverlay) findViewById(R.id.bottombar_options_overlay); 11856688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren mOptionsLayout 11956688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren = (TopRightWeightedLayout) findViewById(R.id.bottombar_options); 1204efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren mCaptureLayout 1214efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren = (FrameLayout) findViewById(R.id.bottombar_capture); 1224efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren mIntentLayout 1234efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren = (TopRightWeightedLayout) findViewById(R.id.bottombar_intent); 124b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague 12539f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague mShutterButton 12639f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague = (ShutterButton) findViewById(R.id.shutter_button); 127b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague mShutterButton.setOnTouchListener(new OnTouchListener() { 128b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague @Override 129b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague public boolean onTouch(View v, MotionEvent event) { 130b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague if (MotionEvent.ACTION_DOWN == event.getActionMasked()) { 131b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague setPaintColor(mBackgroundAlpha, mBackgroundPressedColor); 132b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague invalidate(); 133b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague } else if (MotionEvent.ACTION_UP == event.getActionMasked()) { 134b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague setPaintColor(mBackgroundAlpha, mBackgroundColor); 135b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague invalidate(); 136b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague } 137b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague 138b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague return false; 139b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague } 140b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague }); 14156688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren 14256688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren mOptionsOverlay.setOnTouchListener(new View.OnTouchListener() { 14339f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague @Override 14439f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague public boolean onTouch(View v, MotionEvent event) { 14539f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague if (event.getActionMasked() == MotionEvent.ACTION_DOWN) { 14639f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague // close options immediately. 14739f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague closeModeOptionsDelayed(BOTTOMBAR_OPTIONS_TIMEOUT_MS); 14856688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren } 14939f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague // Let touch event reach mode options or shutter. 15039f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague return false; 15139f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague } 15239f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague }); 15356688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren } 15456688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren 15556688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren @Override 15656688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren public void onPreviewTouched(MotionEvent ev) { 15756688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren // close options immediately. 15856688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren closeModeOptionsDelayed(0); 15956688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren } 16056688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren 16156688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren /** 16256688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren * Schedule (or re-schedule) the options menu to be closed 16356688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren * after a number of milliseconds. If the options menu 16456688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren * is already closed, nothing is scheduled. 16556688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren */ 16656688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren private void closeModeOptionsDelayed(int milliseconds) { 16756688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren // Check that the bottom bar options are visible. 16856688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren if (mOptionsLayout.getVisibility() != View.VISIBLE) { 16956688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren return; 17056688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren } 17156688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren 17256688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren // Remove queued callbacks. 17356688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren removeCallbacks(mCloseOptionsRunnable); 17456688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren 17556688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren // Close the bottom bar options view in n milliseconds. 17656688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren postDelayed(mCloseOptionsRunnable, milliseconds); 1774efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren } 1784efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren 1794efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren /** 1804efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren * Initializes the bottom bar toggle for switching between 18156688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren * capture and the bottom bar options. 1824efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren */ 18356688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren public void setupToggle(boolean isCaptureIntent) { 18456688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren mIsCaptureIntent = isCaptureIntent; 18556688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren 1864efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren // Of type ToggleImageButton because ToggleButton 1874efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren // has a non-removable spacing for text on the right-hand side. 18856688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren mOptionsToggle = (ToggleImageButton) findViewById(R.id.bottombar_options_toggle); 18956688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren mOptionsToggle.setState(0, false); 19056688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren mOptionsToggle.setOnStateChangeListener(new ToggleImageButton.OnStateChangeListener() { 1913b92e2f8e6d91af1b83c8bee95bd93e7153b96daSpike Sprague @Override 19256688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren public void stateChanged(View view, boolean toOptions) { 19356688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren if (toOptions) { 19456688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren if (mIsCaptureIntent) { 1953b92e2f8e6d91af1b83c8bee95bd93e7153b96daSpike Sprague hideIntentLayout(); 1963b92e2f8e6d91af1b83c8bee95bd93e7153b96daSpike Sprague } 19756688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren transitionToOptions(); 1983b92e2f8e6d91af1b83c8bee95bd93e7153b96daSpike Sprague } else { 19956688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren if (mIsCaptureIntent) { 2003b92e2f8e6d91af1b83c8bee95bd93e7153b96daSpike Sprague transitionToIntentLayout(); 2014efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren } else { 2023b92e2f8e6d91af1b83c8bee95bd93e7153b96daSpike Sprague transitionToCapture(); 2034efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren } 2044efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren } 2053b92e2f8e6d91af1b83c8bee95bd93e7153b96daSpike Sprague } 2063b92e2f8e6d91af1b83c8bee95bd93e7153b96daSpike Sprague }); 20756688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren mOptionsOverlay.setReferenceViewParent(mOptionsLayout); 2084efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren } 2094efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren 2104efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren /** 2114efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren * Hide the intent layout. This is necessary for switching between 21256688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren * the intent capture layout and the bottom bar options. 2134efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren */ 2144efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren private void hideIntentLayout() { 2154efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren mIntentLayout.setVisibility(View.INVISIBLE); 2164efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren } 2174efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren 2184efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren /** 21956688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren * Perform a transition from the bottom bar options layout to the 22056688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren * bottom bar capture layout. 2214efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren */ 2224efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren private void transitionToCapture() { 22356688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren mOptionsLayout.setVisibility(View.INVISIBLE); 2244efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren mCaptureLayout.setVisibility(View.VISIBLE); 2254efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren } 2264efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren 2274efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren /** 22856688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren * Perform a transition from the bottom bar capture layout to the 22956688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren * bottom bar options layout. 2304efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren */ 23156688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren private void transitionToOptions() { 2323b92e2f8e6d91af1b83c8bee95bd93e7153b96daSpike Sprague mCaptureLayout.setVisibility(View.INVISIBLE); 23356688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren mOptionsLayout.setVisibility(View.VISIBLE); 2344efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren } 2354efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren 2360744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen /** 2374efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren * Perform a transition to the global intent layout. The current 2384efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren * layout state of the bottom bar is irrelevant. 2390f3c4b4fc9ac87d7d4c3d04c3cb3426c711f57eaSpike Sprague */ 2404efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren public void transitionToIntentLayout() { 2414efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren mCaptureLayout.setVisibility(View.VISIBLE); 24256688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren mOptionsLayout.setVisibility(View.INVISIBLE); 24356688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren mOptionsOverlay.setVisibility(View.VISIBLE); 2444efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren mIntentLayout.setVisibility(View.VISIBLE); 2454efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren 2464efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren View button; 2474efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren button = mIntentLayout.findViewById(R.id.done_button); 2484efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren button.setVisibility(View.INVISIBLE); 2494efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren button = mIntentLayout.findViewById(R.id.retake_button); 2504efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren button.setVisibility(View.INVISIBLE); 2514efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren } 2524efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren 2534efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren /** 2544efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren * Perform a transition to the global intent review layout. 2554efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren * The current layout state of the bottom bar is irrelevant. 2564efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren */ 2574efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren public void transitionToIntentReviewLayout() { 2584efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren mCaptureLayout.setVisibility(View.INVISIBLE); 25956688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren mOptionsLayout.setVisibility(View.INVISIBLE); 26056688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren mOptionsOverlay.setVisibility(View.INVISIBLE); 2614efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren 2624efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren View button; 2634efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren button = mIntentLayout.findViewById(R.id.done_button); 2644efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren button.setVisibility(View.VISIBLE); 2654efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren button = mIntentLayout.findViewById(R.id.retake_button); 2664efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren button.setVisibility(View.VISIBLE); 2674efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren mIntentLayout.setVisibility(View.VISIBLE); 2680f3c4b4fc9ac87d7d4c3d04c3cb3426c711f57eaSpike Sprague } 2690f3c4b4fc9ac87d7d4c3d04c3cb3426c711f57eaSpike Sprague 27070da918464276b110c43868caa272c97baadb89eDoris Liu @Override 27170da918464276b110c43868caa272c97baadb89eDoris Liu public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 27270da918464276b110c43868caa272c97baadb89eDoris Liu mWidth = MeasureSpec.getSize(widthMeasureSpec); 27370da918464276b110c43868caa272c97baadb89eDoris Liu mHeight = MeasureSpec.getSize(heightMeasureSpec); 27470da918464276b110c43868caa272c97baadb89eDoris Liu if (mWidth == 0 || mHeight == 0) { 27570da918464276b110c43868caa272c97baadb89eDoris Liu return; 27670da918464276b110c43868caa272c97baadb89eDoris Liu } 27770da918464276b110c43868caa272c97baadb89eDoris Liu 27870da918464276b110c43868caa272c97baadb89eDoris Liu if (mOffsetShorterEdge != 0 && mOffsetLongerEdge != 0) { 27970da918464276b110c43868caa272c97baadb89eDoris Liu float previewAspectRatio = 28070da918464276b110c43868caa272c97baadb89eDoris Liu mOffsetLongerEdge / mOffsetShorterEdge; 28170da918464276b110c43868caa272c97baadb89eDoris Liu if (previewAspectRatio < 1.0) { 28270da918464276b110c43868caa272c97baadb89eDoris Liu previewAspectRatio = 1.0f/previewAspectRatio; 28370da918464276b110c43868caa272c97baadb89eDoris Liu } 28470da918464276b110c43868caa272c97baadb89eDoris Liu float screenAspectRatio = (float) mWidth / (float) mHeight; 28570da918464276b110c43868caa272c97baadb89eDoris Liu if (screenAspectRatio < 1.0) { 28670da918464276b110c43868caa272c97baadb89eDoris Liu screenAspectRatio = 1.0f/screenAspectRatio; 28770da918464276b110c43868caa272c97baadb89eDoris Liu } 28870da918464276b110c43868caa272c97baadb89eDoris Liu if (previewAspectRatio >= screenAspectRatio) { 28970da918464276b110c43868caa272c97baadb89eDoris Liu mOverLayBottomBar = true; 29039f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague setBackgroundAlpha(128); 29170da918464276b110c43868caa272c97baadb89eDoris Liu } else { 29270da918464276b110c43868caa272c97baadb89eDoris Liu mOverLayBottomBar = false; 29339f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague setBackgroundAlpha(255); 29470da918464276b110c43868caa272c97baadb89eDoris Liu } 29570da918464276b110c43868caa272c97baadb89eDoris Liu } 29670da918464276b110c43868caa272c97baadb89eDoris Liu 29770da918464276b110c43868caa272c97baadb89eDoris Liu // Calculates the width and height needed for the bar. 29870da918464276b110c43868caa272c97baadb89eDoris Liu int barWidth, barHeight; 29970da918464276b110c43868caa272c97baadb89eDoris Liu if (mWidth > mHeight) { 3001648c36927501ff32bf2918e8a445118d5208731Erin Dahlgren // TODO: The bottom bar should not need to care about the 3011648c36927501ff32bf2918e8a445118d5208731Erin Dahlgren // the type of its parent. Handle this in the parent layout. 3021648c36927501ff32bf2918e8a445118d5208731Erin Dahlgren ((LinearLayout.LayoutParams) getLayoutParams()).gravity = Gravity.RIGHT; 30370da918464276b110c43868caa272c97baadb89eDoris Liu if ((mOffsetLongerEdge == 0 && mOffsetShorterEdge == 0) || mOverLayBottomBar) { 30470da918464276b110c43868caa272c97baadb89eDoris Liu barWidth = mOptimalHeight; 30570da918464276b110c43868caa272c97baadb89eDoris Liu barHeight = mHeight; 30670da918464276b110c43868caa272c97baadb89eDoris Liu } else { 30770da918464276b110c43868caa272c97baadb89eDoris Liu barWidth = (int) (mWidth - mOffsetLongerEdge); 30870da918464276b110c43868caa272c97baadb89eDoris Liu barHeight = mHeight; 30970da918464276b110c43868caa272c97baadb89eDoris Liu } 3100744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen } else { 3111648c36927501ff32bf2918e8a445118d5208731Erin Dahlgren ((LinearLayout.LayoutParams) getLayoutParams()).gravity = Gravity.BOTTOM; 31270da918464276b110c43868caa272c97baadb89eDoris Liu if ((mOffsetLongerEdge == 0 && mOffsetShorterEdge == 0) || mOverLayBottomBar) { 31370da918464276b110c43868caa272c97baadb89eDoris Liu barWidth = mWidth; 31470da918464276b110c43868caa272c97baadb89eDoris Liu barHeight = mOptimalHeight; 31570da918464276b110c43868caa272c97baadb89eDoris Liu } else { 31670da918464276b110c43868caa272c97baadb89eDoris Liu barWidth = mWidth; 31770da918464276b110c43868caa272c97baadb89eDoris Liu barHeight = (int) (mHeight - mOffsetLongerEdge); 31870da918464276b110c43868caa272c97baadb89eDoris Liu } 3190744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen } 32039f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague 32139f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague mCirclePath.addCircle( 32239f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague barWidth/2, 32339f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague barHeight/2, 32439f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague (int)(diagonalLength(barWidth, barHeight)/2), 32539f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague Path.Direction.CW); 32639f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague 32770da918464276b110c43868caa272c97baadb89eDoris Liu super.onMeasure(MeasureSpec.makeMeasureSpec(barWidth, MeasureSpec.EXACTLY), 32870da918464276b110c43868caa272c97baadb89eDoris Liu MeasureSpec.makeMeasureSpec(barHeight, MeasureSpec.EXACTLY)); 32970da918464276b110c43868caa272c97baadb89eDoris Liu } 33070da918464276b110c43868caa272c97baadb89eDoris Liu 33170da918464276b110c43868caa272c97baadb89eDoris Liu private void adjustBottomBar(float scaledTextureWidth, 33270da918464276b110c43868caa272c97baadb89eDoris Liu float scaledTextureHeight) { 33370da918464276b110c43868caa272c97baadb89eDoris Liu setOffset(scaledTextureWidth, scaledTextureHeight); 33470da918464276b110c43868caa272c97baadb89eDoris Liu } 33570da918464276b110c43868caa272c97baadb89eDoris Liu 33670da918464276b110c43868caa272c97baadb89eDoris Liu @Override 337482de029dc20e0a577388a602985fb31c3200309Doris Liu public void onPreviewAreaSizeChanged(float scaledTextureWidth, 338482de029dc20e0a577388a602985fb31c3200309Doris Liu float scaledTextureHeight) { 33970da918464276b110c43868caa272c97baadb89eDoris Liu adjustBottomBar(scaledTextureWidth, scaledTextureHeight); 34070da918464276b110c43868caa272c97baadb89eDoris Liu } 34170da918464276b110c43868caa272c97baadb89eDoris Liu 34270da918464276b110c43868caa272c97baadb89eDoris Liu private void setOffset(float scaledTextureWidth, float scaledTextureHeight) { 34370da918464276b110c43868caa272c97baadb89eDoris Liu float offsetLongerEdge, offsetShorterEdge; 34470da918464276b110c43868caa272c97baadb89eDoris Liu if (scaledTextureHeight > scaledTextureWidth) { 34570da918464276b110c43868caa272c97baadb89eDoris Liu offsetLongerEdge = scaledTextureHeight; 34670da918464276b110c43868caa272c97baadb89eDoris Liu offsetShorterEdge = scaledTextureWidth; 3470744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen } else { 34870da918464276b110c43868caa272c97baadb89eDoris Liu offsetLongerEdge = scaledTextureWidth; 34970da918464276b110c43868caa272c97baadb89eDoris Liu offsetShorterEdge = scaledTextureHeight; 35070da918464276b110c43868caa272c97baadb89eDoris Liu } 35170da918464276b110c43868caa272c97baadb89eDoris Liu if (mOffsetLongerEdge != offsetLongerEdge || mOffsetShorterEdge != offsetShorterEdge) { 35270da918464276b110c43868caa272c97baadb89eDoris Liu mOffsetLongerEdge = offsetLongerEdge; 35370da918464276b110c43868caa272c97baadb89eDoris Liu mOffsetShorterEdge = offsetShorterEdge; 35470da918464276b110c43868caa272c97baadb89eDoris Liu requestLayout(); 3550744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen } 3560744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen } 3570744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen 3580744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen @Override 3590744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen protected void onConfigurationChanged(Configuration config) { 3600744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen super.onConfigurationChanged(config); 3610744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen } 3620744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen 363e3b0e946924e45f6788db69aaa8f48a2d81031f0Spike Sprague // prevent touches on bottom bar (not its children) 364e3b0e946924e45f6788db69aaa8f48a2d81031f0Spike Sprague // from triggering a touch event on preview area 365e3b0e946924e45f6788db69aaa8f48a2d81031f0Spike Sprague @Override 366e3b0e946924e45f6788db69aaa8f48a2d81031f0Spike Sprague public boolean onTouchEvent(MotionEvent event) { 367e3b0e946924e45f6788db69aaa8f48a2d81031f0Spike Sprague return true; 368e3b0e946924e45f6788db69aaa8f48a2d81031f0Spike Sprague } 36939f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague 37039f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague @Override 37139f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague public void onDraw(Canvas canvas) { 37239f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague canvas.drawPath(mCirclePath, mCirclePaint); 37339f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague 37439f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague super.onDraw(canvas); 37539f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague } 37639f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague 37739f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague @Override 37839f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague public void setBackgroundColor(int color) { 37939f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague mBackgroundColor = color; 380b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague setPaintColor(mBackgroundAlpha, mBackgroundColor); 381b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague } 382b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague 383b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague public void setBackgroundPressedColor(int color) { 384b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague mBackgroundPressedColor = color; 38539f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague } 38639f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague 38739f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague public void setBackgroundAlpha(int alpha) { 388b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague mBackgroundAlpha = alpha; 389b92910e04c4da91fc4ea5a9484b83f9ecba1c896Spike Sprague setPaintColor(mBackgroundAlpha, mBackgroundColor); 39039f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague } 39139f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague 39239f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague private double diagonalLength(double w, double h) { 39339f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague return Math.sqrt((w*w) + (h*h)); 39439f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague } 39539f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague private double diagonalLength() { 39639f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague return diagonalLength(getWidth(), getHeight()); 39739f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague } 39839f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague 39939f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague private TransitionDrawable crossfadeDrawable(Drawable from, Drawable to) { 40039f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague Drawable [] arrayDrawable = new Drawable[2]; 40139f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague arrayDrawable[0] = from; 40239f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague arrayDrawable[1] = to; 40339f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague TransitionDrawable transitionDrawable = new TransitionDrawable(arrayDrawable); 40439f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague transitionDrawable.setCrossFadeEnabled(true); 40539f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague return transitionDrawable; 40639f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague } 40739f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague 40839f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague /** 40939f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague * Set the shutter button's icon resource 41039f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague */ 41139f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague public void setShutterButtonIcon(int resId) { 41239f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague mShutterButton.setImageResource(resId); 41339f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague } 41439f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague 41539f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague /** 41639f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague * Animates bar to a single stop button 41739f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague */ 41839f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague public void animateToCircle(int resId) { 41939f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague final ValueAnimator radiusAnimator = ValueAnimator.ofFloat( 42039f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague (float) diagonalLength()/2, 42139f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague CIRCLE_RADIUS); 42239f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague radiusAnimator.setDuration(CIRCLE_ANIM_DURATION_MS); 42339f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague radiusAnimator.setInterpolator(Gusterpolator.INSTANCE); 42439f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague 42539f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague radiusAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 42639f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague @Override 42739f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague public void onAnimationUpdate(ValueAnimator animation) { 42839f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague mCirclePath.reset(); 42939f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague mCirclePath.addCircle( 43039f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague getWidth()/2, 43139f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague getHeight()/2, 43239f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague (Float) animation.getAnimatedValue(), 43339f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague Path.Direction.CW); 43439f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague 43539f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague invalidate(); 43639f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague } 43739f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague }); 43839f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague 43939f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague TransitionDrawable transitionDrawable = crossfadeDrawable( 44039f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague mShutterButton.getDrawable(), 44139f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague getResources().getDrawable(resId)); 44239f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague mShutterButton.setImageDrawable(transitionDrawable); 44339f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague 44439f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague View optionsOverlay = findViewById(R.id.bottombar_options_overlay); 44539f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague optionsOverlay.setVisibility(View.INVISIBLE); 44639f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague 44739f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague 44839f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague transitionDrawable.startTransition(CIRCLE_ANIM_DURATION_MS); 44939f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague radiusAnimator.start(); 45039f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague } 45139f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague 45239f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague /** 45339f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague * Animates bar to full width / length with video capture icon 45439f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague */ 45539f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague public void animateToFullSize(int resId) { 45639f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague final ValueAnimator radiusAnimator = ValueAnimator.ofFloat( 45739f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague CIRCLE_RADIUS, 45839f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague (float) diagonalLength()/2); 45939f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague radiusAnimator.setDuration(CIRCLE_ANIM_DURATION_MS); 46039f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague radiusAnimator.setInterpolator(Gusterpolator.INSTANCE); 46139f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague radiusAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 46239f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague @Override 46339f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague public void onAnimationUpdate(ValueAnimator animation) { 46439f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague mCirclePath.reset(); 46539f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague mCirclePath.addCircle( 46639f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague getWidth()/2, 46739f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague getHeight()/2, 46839f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague (Float) animation.getAnimatedValue(), 46939f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague Path.Direction.CW); 47039f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague 47139f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague invalidate(); 47239f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague } 47339f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague }); 47439f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague radiusAnimator.addListener(new AnimatorListenerAdapter() { 47539f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague @Override 47639f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague public void onAnimationEnd(Animator animation) { 47739f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague View optionsOverlay = findViewById(R.id.bottombar_options_overlay); 47839f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague optionsOverlay.setVisibility(View.VISIBLE); 47939f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague } 48039f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague }); 48139f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague 48239f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague TransitionDrawable transitionDrawable = crossfadeDrawable( 48339f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague mShutterButton.getDrawable(), 48439f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague getResources().getDrawable(resId)); 48539f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague mShutterButton.setImageDrawable(transitionDrawable); 48639f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague 48739f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague transitionDrawable.startTransition(CIRCLE_ANIM_DURATION_MS); 48839f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague radiusAnimator.start(); 48939f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague } 4900744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen} 491