BottomBar.java revision 39f8a7647aa4051a1c260b9496c2db82f93f8667
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; 9939f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague private Paint mCirclePaint = new Paint(); 10039f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague private Path mCirclePath = new Path(); 10139f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague 1020744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen public BottomBar(Context context, AttributeSet attrs) { 1030744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen super(context, attrs); 10470da918464276b110c43868caa272c97baadb89eDoris Liu mOptimalHeight = getResources().getDimensionPixelSize(R.dimen.bottom_bar_height_optimal); 1050744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen } 1060744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen 1074efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren @Override 1084efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren public void onFinishInflate() { 10956688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren mOptionsOverlay 11056688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren = (TopRightMostOverlay) findViewById(R.id.bottombar_options_overlay); 11156688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren mOptionsLayout 11256688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren = (TopRightWeightedLayout) findViewById(R.id.bottombar_options); 1134efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren mCaptureLayout 1144efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren = (FrameLayout) findViewById(R.id.bottombar_capture); 1154efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren mIntentLayout 1164efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren = (TopRightWeightedLayout) findViewById(R.id.bottombar_intent); 11739f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague mShutterButton 11839f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague = (ShutterButton) findViewById(R.id.shutter_button); 11956688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren 12056688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren mOptionsOverlay.setOnTouchListener(new View.OnTouchListener() { 12139f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague @Override 12239f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague public boolean onTouch(View v, MotionEvent event) { 12339f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague if (event.getActionMasked() == MotionEvent.ACTION_DOWN) { 12439f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague // close options immediately. 12539f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague closeModeOptionsDelayed(BOTTOMBAR_OPTIONS_TIMEOUT_MS); 12656688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren } 12739f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague // Let touch event reach mode options or shutter. 12839f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague return false; 12939f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague } 13039f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague }); 13156688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren } 13256688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren 13356688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren @Override 13456688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren public void onPreviewTouched(MotionEvent ev) { 13556688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren // close options immediately. 13656688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren closeModeOptionsDelayed(0); 13756688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren } 13856688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren 13956688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren /** 14056688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren * Schedule (or re-schedule) the options menu to be closed 14156688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren * after a number of milliseconds. If the options menu 14256688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren * is already closed, nothing is scheduled. 14356688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren */ 14456688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren private void closeModeOptionsDelayed(int milliseconds) { 14556688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren // Check that the bottom bar options are visible. 14656688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren if (mOptionsLayout.getVisibility() != View.VISIBLE) { 14756688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren return; 14856688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren } 14956688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren 15056688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren // Remove queued callbacks. 15156688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren removeCallbacks(mCloseOptionsRunnable); 15256688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren 15356688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren // Close the bottom bar options view in n milliseconds. 15456688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren postDelayed(mCloseOptionsRunnable, milliseconds); 1554efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren } 1564efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren 1574efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren /** 1584efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren * Initializes the bottom bar toggle for switching between 15956688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren * capture and the bottom bar options. 1604efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren */ 16156688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren public void setupToggle(boolean isCaptureIntent) { 16256688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren mIsCaptureIntent = isCaptureIntent; 16356688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren 1644efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren // Of type ToggleImageButton because ToggleButton 1654efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren // has a non-removable spacing for text on the right-hand side. 16656688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren mOptionsToggle = (ToggleImageButton) findViewById(R.id.bottombar_options_toggle); 16756688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren mOptionsToggle.setState(0, false); 16856688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren mOptionsToggle.setOnStateChangeListener(new ToggleImageButton.OnStateChangeListener() { 1693b92e2f8e6d91af1b83c8bee95bd93e7153b96daSpike Sprague @Override 17056688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren public void stateChanged(View view, boolean toOptions) { 17156688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren if (toOptions) { 17256688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren if (mIsCaptureIntent) { 1733b92e2f8e6d91af1b83c8bee95bd93e7153b96daSpike Sprague hideIntentLayout(); 1743b92e2f8e6d91af1b83c8bee95bd93e7153b96daSpike Sprague } 17556688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren transitionToOptions(); 1763b92e2f8e6d91af1b83c8bee95bd93e7153b96daSpike Sprague } else { 17756688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren if (mIsCaptureIntent) { 1783b92e2f8e6d91af1b83c8bee95bd93e7153b96daSpike Sprague transitionToIntentLayout(); 1794efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren } else { 1803b92e2f8e6d91af1b83c8bee95bd93e7153b96daSpike Sprague transitionToCapture(); 1814efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren } 1824efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren } 1833b92e2f8e6d91af1b83c8bee95bd93e7153b96daSpike Sprague } 1843b92e2f8e6d91af1b83c8bee95bd93e7153b96daSpike Sprague }); 18556688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren mOptionsOverlay.setReferenceViewParent(mOptionsLayout); 1864efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren } 1874efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren 1884efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren /** 1894efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren * Hide the intent layout. This is necessary for switching between 19056688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren * the intent capture layout and the bottom bar options. 1914efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren */ 1924efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren private void hideIntentLayout() { 1934efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren mIntentLayout.setVisibility(View.INVISIBLE); 1944efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren } 1954efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren 1964efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren /** 19756688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren * Perform a transition from the bottom bar options layout to the 19856688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren * bottom bar capture layout. 1994efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren */ 2004efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren private void transitionToCapture() { 20156688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren mOptionsLayout.setVisibility(View.INVISIBLE); 2024efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren mCaptureLayout.setVisibility(View.VISIBLE); 2034efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren } 2044efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren 2054efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren /** 20656688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren * Perform a transition from the bottom bar capture layout to the 20756688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren * bottom bar options layout. 2084efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren */ 20956688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren private void transitionToOptions() { 2103b92e2f8e6d91af1b83c8bee95bd93e7153b96daSpike Sprague mCaptureLayout.setVisibility(View.INVISIBLE); 21156688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren mOptionsLayout.setVisibility(View.VISIBLE); 2124efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren } 2134efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren 2140744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen /** 2154efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren * Perform a transition to the global intent layout. The current 2164efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren * layout state of the bottom bar is irrelevant. 2170f3c4b4fc9ac87d7d4c3d04c3cb3426c711f57eaSpike Sprague */ 2184efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren public void transitionToIntentLayout() { 2194efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren mCaptureLayout.setVisibility(View.VISIBLE); 22056688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren mOptionsLayout.setVisibility(View.INVISIBLE); 22156688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren mOptionsOverlay.setVisibility(View.VISIBLE); 2224efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren mIntentLayout.setVisibility(View.VISIBLE); 2234efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren 2244efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren View button; 2254efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren button = mIntentLayout.findViewById(R.id.done_button); 2264efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren button.setVisibility(View.INVISIBLE); 2274efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren button = mIntentLayout.findViewById(R.id.retake_button); 2284efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren button.setVisibility(View.INVISIBLE); 2294efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren } 2304efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren 2314efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren /** 2324efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren * Perform a transition to the global intent review layout. 2334efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren * The current layout state of the bottom bar is irrelevant. 2344efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren */ 2354efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren public void transitionToIntentReviewLayout() { 2364efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren mCaptureLayout.setVisibility(View.INVISIBLE); 23756688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren mOptionsLayout.setVisibility(View.INVISIBLE); 23856688f7019fbe4dee110b7600349f48da9fff601Erin Dahlgren mOptionsOverlay.setVisibility(View.INVISIBLE); 2394efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren 2404efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren View button; 2414efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren button = mIntentLayout.findViewById(R.id.done_button); 2424efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren button.setVisibility(View.VISIBLE); 2434efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren button = mIntentLayout.findViewById(R.id.retake_button); 2444efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren button.setVisibility(View.VISIBLE); 2454efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren mIntentLayout.setVisibility(View.VISIBLE); 2460f3c4b4fc9ac87d7d4c3d04c3cb3426c711f57eaSpike Sprague } 2470f3c4b4fc9ac87d7d4c3d04c3cb3426c711f57eaSpike Sprague 24870da918464276b110c43868caa272c97baadb89eDoris Liu @Override 24970da918464276b110c43868caa272c97baadb89eDoris Liu public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 25070da918464276b110c43868caa272c97baadb89eDoris Liu mWidth = MeasureSpec.getSize(widthMeasureSpec); 25170da918464276b110c43868caa272c97baadb89eDoris Liu mHeight = MeasureSpec.getSize(heightMeasureSpec); 25270da918464276b110c43868caa272c97baadb89eDoris Liu if (mWidth == 0 || mHeight == 0) { 25370da918464276b110c43868caa272c97baadb89eDoris Liu return; 25470da918464276b110c43868caa272c97baadb89eDoris Liu } 25570da918464276b110c43868caa272c97baadb89eDoris Liu 25670da918464276b110c43868caa272c97baadb89eDoris Liu if (mOffsetShorterEdge != 0 && mOffsetLongerEdge != 0) { 25770da918464276b110c43868caa272c97baadb89eDoris Liu float previewAspectRatio = 25870da918464276b110c43868caa272c97baadb89eDoris Liu mOffsetLongerEdge / mOffsetShorterEdge; 25970da918464276b110c43868caa272c97baadb89eDoris Liu if (previewAspectRatio < 1.0) { 26070da918464276b110c43868caa272c97baadb89eDoris Liu previewAspectRatio = 1.0f/previewAspectRatio; 26170da918464276b110c43868caa272c97baadb89eDoris Liu } 26270da918464276b110c43868caa272c97baadb89eDoris Liu float screenAspectRatio = (float) mWidth / (float) mHeight; 26370da918464276b110c43868caa272c97baadb89eDoris Liu if (screenAspectRatio < 1.0) { 26470da918464276b110c43868caa272c97baadb89eDoris Liu screenAspectRatio = 1.0f/screenAspectRatio; 26570da918464276b110c43868caa272c97baadb89eDoris Liu } 26670da918464276b110c43868caa272c97baadb89eDoris Liu if (previewAspectRatio >= screenAspectRatio) { 26770da918464276b110c43868caa272c97baadb89eDoris Liu mOverLayBottomBar = true; 26839f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague setBackgroundAlpha(128); 26970da918464276b110c43868caa272c97baadb89eDoris Liu } else { 27070da918464276b110c43868caa272c97baadb89eDoris Liu mOverLayBottomBar = false; 27139f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague setBackgroundAlpha(255); 27270da918464276b110c43868caa272c97baadb89eDoris Liu } 27370da918464276b110c43868caa272c97baadb89eDoris Liu } 27470da918464276b110c43868caa272c97baadb89eDoris Liu 27570da918464276b110c43868caa272c97baadb89eDoris Liu // Calculates the width and height needed for the bar. 27670da918464276b110c43868caa272c97baadb89eDoris Liu int barWidth, barHeight; 27770da918464276b110c43868caa272c97baadb89eDoris Liu if (mWidth > mHeight) { 2781648c36927501ff32bf2918e8a445118d5208731Erin Dahlgren // TODO: The bottom bar should not need to care about the 2791648c36927501ff32bf2918e8a445118d5208731Erin Dahlgren // the type of its parent. Handle this in the parent layout. 2801648c36927501ff32bf2918e8a445118d5208731Erin Dahlgren ((LinearLayout.LayoutParams) getLayoutParams()).gravity = Gravity.RIGHT; 28170da918464276b110c43868caa272c97baadb89eDoris Liu if ((mOffsetLongerEdge == 0 && mOffsetShorterEdge == 0) || mOverLayBottomBar) { 28270da918464276b110c43868caa272c97baadb89eDoris Liu barWidth = mOptimalHeight; 28370da918464276b110c43868caa272c97baadb89eDoris Liu barHeight = mHeight; 28470da918464276b110c43868caa272c97baadb89eDoris Liu } else { 28570da918464276b110c43868caa272c97baadb89eDoris Liu barWidth = (int) (mWidth - mOffsetLongerEdge); 28670da918464276b110c43868caa272c97baadb89eDoris Liu barHeight = mHeight; 28770da918464276b110c43868caa272c97baadb89eDoris Liu } 2880744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen } else { 2891648c36927501ff32bf2918e8a445118d5208731Erin Dahlgren ((LinearLayout.LayoutParams) getLayoutParams()).gravity = Gravity.BOTTOM; 29070da918464276b110c43868caa272c97baadb89eDoris Liu if ((mOffsetLongerEdge == 0 && mOffsetShorterEdge == 0) || mOverLayBottomBar) { 29170da918464276b110c43868caa272c97baadb89eDoris Liu barWidth = mWidth; 29270da918464276b110c43868caa272c97baadb89eDoris Liu barHeight = mOptimalHeight; 29370da918464276b110c43868caa272c97baadb89eDoris Liu } else { 29470da918464276b110c43868caa272c97baadb89eDoris Liu barWidth = mWidth; 29570da918464276b110c43868caa272c97baadb89eDoris Liu barHeight = (int) (mHeight - mOffsetLongerEdge); 29670da918464276b110c43868caa272c97baadb89eDoris Liu } 2970744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen } 29839f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague 29939f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague mCirclePath.addCircle( 30039f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague barWidth/2, 30139f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague barHeight/2, 30239f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague (int)(diagonalLength(barWidth, barHeight)/2), 30339f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague Path.Direction.CW); 30439f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague 30570da918464276b110c43868caa272c97baadb89eDoris Liu super.onMeasure(MeasureSpec.makeMeasureSpec(barWidth, MeasureSpec.EXACTLY), 30670da918464276b110c43868caa272c97baadb89eDoris Liu MeasureSpec.makeMeasureSpec(barHeight, MeasureSpec.EXACTLY)); 30770da918464276b110c43868caa272c97baadb89eDoris Liu } 30870da918464276b110c43868caa272c97baadb89eDoris Liu 30970da918464276b110c43868caa272c97baadb89eDoris Liu private void adjustBottomBar(float scaledTextureWidth, 31070da918464276b110c43868caa272c97baadb89eDoris Liu float scaledTextureHeight) { 31170da918464276b110c43868caa272c97baadb89eDoris Liu setOffset(scaledTextureWidth, scaledTextureHeight); 31270da918464276b110c43868caa272c97baadb89eDoris Liu } 31370da918464276b110c43868caa272c97baadb89eDoris Liu 31470da918464276b110c43868caa272c97baadb89eDoris Liu @Override 315482de029dc20e0a577388a602985fb31c3200309Doris Liu public void onPreviewAreaSizeChanged(float scaledTextureWidth, 316482de029dc20e0a577388a602985fb31c3200309Doris Liu float scaledTextureHeight) { 31770da918464276b110c43868caa272c97baadb89eDoris Liu adjustBottomBar(scaledTextureWidth, scaledTextureHeight); 31870da918464276b110c43868caa272c97baadb89eDoris Liu } 31970da918464276b110c43868caa272c97baadb89eDoris Liu 32070da918464276b110c43868caa272c97baadb89eDoris Liu private void setOffset(float scaledTextureWidth, float scaledTextureHeight) { 32170da918464276b110c43868caa272c97baadb89eDoris Liu float offsetLongerEdge, offsetShorterEdge; 32270da918464276b110c43868caa272c97baadb89eDoris Liu if (scaledTextureHeight > scaledTextureWidth) { 32370da918464276b110c43868caa272c97baadb89eDoris Liu offsetLongerEdge = scaledTextureHeight; 32470da918464276b110c43868caa272c97baadb89eDoris Liu offsetShorterEdge = scaledTextureWidth; 3250744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen } else { 32670da918464276b110c43868caa272c97baadb89eDoris Liu offsetLongerEdge = scaledTextureWidth; 32770da918464276b110c43868caa272c97baadb89eDoris Liu offsetShorterEdge = scaledTextureHeight; 32870da918464276b110c43868caa272c97baadb89eDoris Liu } 32970da918464276b110c43868caa272c97baadb89eDoris Liu if (mOffsetLongerEdge != offsetLongerEdge || mOffsetShorterEdge != offsetShorterEdge) { 33070da918464276b110c43868caa272c97baadb89eDoris Liu mOffsetLongerEdge = offsetLongerEdge; 33170da918464276b110c43868caa272c97baadb89eDoris Liu mOffsetShorterEdge = offsetShorterEdge; 33270da918464276b110c43868caa272c97baadb89eDoris Liu requestLayout(); 3330744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen } 3340744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen } 3350744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen 3360744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen @Override 3370744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen protected void onConfigurationChanged(Configuration config) { 3380744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen super.onConfigurationChanged(config); 3390744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen } 3400744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen 341e3b0e946924e45f6788db69aaa8f48a2d81031f0Spike Sprague // prevent touches on bottom bar (not its children) 342e3b0e946924e45f6788db69aaa8f48a2d81031f0Spike Sprague // from triggering a touch event on preview area 343e3b0e946924e45f6788db69aaa8f48a2d81031f0Spike Sprague @Override 344e3b0e946924e45f6788db69aaa8f48a2d81031f0Spike Sprague public boolean onTouchEvent(MotionEvent event) { 345e3b0e946924e45f6788db69aaa8f48a2d81031f0Spike Sprague return true; 346e3b0e946924e45f6788db69aaa8f48a2d81031f0Spike Sprague } 34739f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague 34839f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague @Override 34939f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague public void onDraw(Canvas canvas) { 35039f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague canvas.drawPath(mCirclePath, mCirclePaint); 35139f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague 35239f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague super.onDraw(canvas); 35339f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague } 35439f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague 35539f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague @Override 35639f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague public void setBackgroundColor(int color) { 35739f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague mBackgroundColor = color; 35839f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague mCirclePaint.setColor(mBackgroundColor); 35939f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague } 36039f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague 36139f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague public void setBackgroundAlpha(int alpha) { 36239f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague setBackgroundColor((alpha << 24) | (mBackgroundColor & 0x00FFFFFF)); 36339f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague } 36439f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague 36539f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague private double diagonalLength(double w, double h) { 36639f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague return Math.sqrt((w*w) + (h*h)); 36739f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague } 36839f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague private double diagonalLength() { 36939f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague return diagonalLength(getWidth(), getHeight()); 37039f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague } 37139f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague 37239f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague private TransitionDrawable crossfadeDrawable(Drawable from, Drawable to) { 37339f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague Drawable [] arrayDrawable = new Drawable[2]; 37439f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague arrayDrawable[0] = from; 37539f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague arrayDrawable[1] = to; 37639f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague TransitionDrawable transitionDrawable = new TransitionDrawable(arrayDrawable); 37739f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague transitionDrawable.setCrossFadeEnabled(true); 37839f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague return transitionDrawable; 37939f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague } 38039f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague 38139f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague /** 38239f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague * Set the shutter button's icon resource 38339f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague */ 38439f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague public void setShutterButtonIcon(int resId) { 38539f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague mShutterButton.setImageResource(resId); 38639f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague } 38739f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague 38839f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague /** 38939f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague * Animates bar to a single stop button 39039f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague */ 39139f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague public void animateToCircle(int resId) { 39239f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague final ValueAnimator radiusAnimator = ValueAnimator.ofFloat( 39339f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague (float) diagonalLength()/2, 39439f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague CIRCLE_RADIUS); 39539f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague radiusAnimator.setDuration(CIRCLE_ANIM_DURATION_MS); 39639f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague radiusAnimator.setInterpolator(Gusterpolator.INSTANCE); 39739f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague 39839f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague radiusAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 39939f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague @Override 40039f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague public void onAnimationUpdate(ValueAnimator animation) { 40139f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague mCirclePath.reset(); 40239f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague mCirclePath.addCircle( 40339f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague getWidth()/2, 40439f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague getHeight()/2, 40539f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague (Float) animation.getAnimatedValue(), 40639f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague Path.Direction.CW); 40739f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague 40839f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague invalidate(); 40939f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague } 41039f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague }); 41139f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague 41239f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague TransitionDrawable transitionDrawable = crossfadeDrawable( 41339f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague mShutterButton.getDrawable(), 41439f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague getResources().getDrawable(resId)); 41539f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague mShutterButton.setImageDrawable(transitionDrawable); 41639f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague 41739f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague View optionsOverlay = findViewById(R.id.bottombar_options_overlay); 41839f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague optionsOverlay.setVisibility(View.INVISIBLE); 41939f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague 42039f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague 42139f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague transitionDrawable.startTransition(CIRCLE_ANIM_DURATION_MS); 42239f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague radiusAnimator.start(); 42339f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague } 42439f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague 42539f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague /** 42639f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague * Animates bar to full width / length with video capture icon 42739f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague */ 42839f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague public void animateToFullSize(int resId) { 42939f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague final ValueAnimator radiusAnimator = ValueAnimator.ofFloat( 43039f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague CIRCLE_RADIUS, 43139f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague (float) diagonalLength()/2); 43239f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague radiusAnimator.setDuration(CIRCLE_ANIM_DURATION_MS); 43339f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague radiusAnimator.setInterpolator(Gusterpolator.INSTANCE); 43439f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague radiusAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 43539f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague @Override 43639f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague public void onAnimationUpdate(ValueAnimator animation) { 43739f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague mCirclePath.reset(); 43839f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague mCirclePath.addCircle( 43939f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague getWidth()/2, 44039f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague getHeight()/2, 44139f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague (Float) animation.getAnimatedValue(), 44239f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague Path.Direction.CW); 44339f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague 44439f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague invalidate(); 44539f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague } 44639f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague }); 44739f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague radiusAnimator.addListener(new AnimatorListenerAdapter() { 44839f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague @Override 44939f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague public void onAnimationEnd(Animator animation) { 45039f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague View optionsOverlay = findViewById(R.id.bottombar_options_overlay); 45139f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague optionsOverlay.setVisibility(View.VISIBLE); 45239f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague } 45339f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague }); 45439f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague 45539f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague TransitionDrawable transitionDrawable = crossfadeDrawable( 45639f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague mShutterButton.getDrawable(), 45739f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague getResources().getDrawable(resId)); 45839f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague mShutterButton.setImageDrawable(transitionDrawable); 45939f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague 46039f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague transitionDrawable.startTransition(CIRCLE_ANIM_DURATION_MS); 46139f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague radiusAnimator.start(); 46239f8a7647aa4051a1c260b9496c2db82f93f8667Spike Sprague } 4630744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen} 464