182fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague/* 282fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague * Copyright (C) 2014 The Android Open Source Project 382fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague * 482fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague * Licensed under the Apache License, Version 2.0 (the "License"); 582fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague * you may not use this file except in compliance with the License. 682fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague * You may obtain a copy of the License at 782fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague * 882fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague * http://www.apache.org/licenses/LICENSE-2.0 982fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague * 1082fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague * Unless required by applicable law or agreed to in writing, software 1182fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague * distributed under the License is distributed on an "AS IS" BASIS, 1282fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1382fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague * See the License for the specific language governing permissions and 1482fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague * limitations under the License. 1582fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague */ 1682fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Spraguepackage com.android.camera.widget; 1782fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague 1854ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Huimport com.google.common.base.Optional; 1954ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu 2082fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Spragueimport android.animation.Animator; 2182fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Spragueimport android.animation.AnimatorListenerAdapter; 2282fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Spragueimport android.animation.AnimatorSet; 2382fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Spragueimport android.animation.ValueAnimator; 2482fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Spragueimport android.content.Context; 2582fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Spragueimport android.content.res.Configuration; 2682fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Spragueimport android.graphics.Canvas; 2782fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Spragueimport android.graphics.Paint; 2882fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Spragueimport android.graphics.RectF; 2918b22b5963e8871e539edf669d96862eec72bb5dSpike Spragueimport android.util.AttributeSet; 3082fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Spragueimport android.view.View; 3156d43cf80d40379d57ac1db697bc014d5c321b91Spike Spragueimport android.view.ViewGroup; 3282fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Spragueimport android.widget.FrameLayout; 33abf54e2994961395a0feb0b08353e62718443f23Spike Spragueimport android.widget.ImageButton; 3482fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague 3518b22b5963e8871e539edf669d96862eec72bb5dSpike Spragueimport com.android.camera.MultiToggleImageButton; 3659345144c4bde59b81bb19c95cdd977c1d1a9cd4Spike Spragueimport com.android.camera.ui.RadioOptions; 3756d43cf80d40379d57ac1db697bc014d5c321b91Spike Spragueimport com.android.camera.ui.TopRightWeightedLayout; 3882fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Spragueimport com.android.camera.util.Gusterpolator; 3982fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Spragueimport com.android.camera2.R; 4082fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague 4156d43cf80d40379d57ac1db697bc014d5c321b91Spike Spragueimport java.util.ArrayList; 4256d43cf80d40379d57ac1db697bc014d5c321b91Spike Sprague 4382fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Spraguepublic class ModeOptions extends FrameLayout { 4482fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague private int mBackgroundColor; 4582fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague private final Paint mPaint = new Paint(); 46591eec6465d29bbc053e164071c4c3a7c260a1d3Spike Sprague private boolean mIsHiddenOrHiding; 4782fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague private RectF mAnimateFrom = new RectF(); 4882fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague private View mViewToShowHide; 4956d43cf80d40379d57ac1db697bc014d5c321b91Spike Sprague private TopRightWeightedLayout mModeOptionsButtons; 5059345144c4bde59b81bb19c95cdd977c1d1a9cd4Spike Sprague private RadioOptions mModeOptionsPano; 5159345144c4bde59b81bb19c95cdd977c1d1a9cd4Spike Sprague private RadioOptions mModeOptionsExposure; 5282fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague 5382fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague private AnimatorSet mVisibleAnimator; 5482fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague private AnimatorSet mHiddenAnimator; 5582fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague private boolean mDrawCircle; 5682fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague private boolean mFill; 5782fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague private static final int RADIUS_ANIMATION_TIME = 250; 5882fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague private static final int SHOW_ALPHA_ANIMATION_TIME = 350; 5982fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague private static final int HIDE_ALPHA_ANIMATION_TIME = 200; 6054ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu public static final int PADDING_ANIMATION_TIME = 350; 6182fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague 6259345144c4bde59b81bb19c95cdd977c1d1a9cd4Spike Sprague private ViewGroup mMainBar; 6359345144c4bde59b81bb19c95cdd977c1d1a9cd4Spike Sprague private ViewGroup mActiveBar; 6459345144c4bde59b81bb19c95cdd977c1d1a9cd4Spike Sprague public static final int BAR_INVALID = -1; 6559345144c4bde59b81bb19c95cdd977c1d1a9cd4Spike Sprague public static final int BAR_STANDARD = 0; 6659345144c4bde59b81bb19c95cdd977c1d1a9cd4Spike Sprague public static final int BAR_PANO = 1; 6759345144c4bde59b81bb19c95cdd977c1d1a9cd4Spike Sprague 6882fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague private boolean mIsPortrait; 694df915872c25fe61640a94c7a2c5f27eee1a1048Doris Liu private float mRadius = 0f; 7082fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague 7154ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu /** 7254ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu * A class implementing this interface will receive callback events from 7354ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu * mode options. 7454ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu */ 7554ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu public interface Listener { 7654ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu /** 7754ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu * Called when about to start animating the mode options from hidden 7854ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu * to visible. 7954ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu */ 8054ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu public void onBeginToShowModeOptions(); 8154ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu 8254ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu /** 8354ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu * Called when about to start animating the mode options from visible 8454ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu * to hidden. 8554ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu */ 8654ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu public void onBeginToHideModeOptions(); 8754ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu } 8854ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu 8954ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu /** The listener. */ 9054ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu private Optional<Listener> mListener; 9154ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu 9282fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague public ModeOptions(Context context, AttributeSet attrs) { 9382fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague super(context, attrs); 9454ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu mListener = Optional.absent(); 9554ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu } 9654ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu 9754ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu /** 9854ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu * Whether the mode options is hidden or in the middle of fading 9954ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu * out. 10054ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu */ 10154ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu public boolean isHiddenOrHiding() { 10254ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu return mIsHiddenOrHiding; 10354ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu } 10454ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu 10554ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu /** 10654ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu * Sets the listener. 10754ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu * 10854ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu * @param listener The listener to be set. 10954ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu */ 11054ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu public void setListener(Listener listener) { 11154ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu mListener = Optional.of(listener); 11282fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague } 11382fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague 11482fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague public void setViewToShowHide(View v) { 11582fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague mViewToShowHide = v; 11682fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague } 11782fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague 11882fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague @Override 11982fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague public void onFinishInflate() { 120591eec6465d29bbc053e164071c4c3a7c260a1d3Spike Sprague mIsHiddenOrHiding = true; 12182fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague mBackgroundColor = getResources().getColor(R.color.mode_options_background); 12282fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague mPaint.setAntiAlias(true); 12382fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague mPaint.setColor(mBackgroundColor); 12456d43cf80d40379d57ac1db697bc014d5c321b91Spike Sprague mModeOptionsButtons = (TopRightWeightedLayout) findViewById(R.id.mode_options_buttons); 12559345144c4bde59b81bb19c95cdd977c1d1a9cd4Spike Sprague mModeOptionsPano = (RadioOptions) findViewById(R.id.mode_options_pano); 12659345144c4bde59b81bb19c95cdd977c1d1a9cd4Spike Sprague mModeOptionsExposure = (RadioOptions) findViewById(R.id.mode_options_exposure); 12759345144c4bde59b81bb19c95cdd977c1d1a9cd4Spike Sprague mMainBar = mActiveBar = mModeOptionsButtons; 128b6c4a314d0a0a185e6d987298ef9b7f4db8a6a2fSenpo Hu } 129abf54e2994961395a0feb0b08353e62718443f23Spike Sprague 130b6c4a314d0a0a185e6d987298ef9b7f4db8a6a2fSenpo Hu public void showExposureOptions() { 131b6c4a314d0a0a185e6d987298ef9b7f4db8a6a2fSenpo Hu mActiveBar = mModeOptionsExposure; 132b6c4a314d0a0a185e6d987298ef9b7f4db8a6a2fSenpo Hu mMainBar.setVisibility(View.INVISIBLE); 133b6c4a314d0a0a185e6d987298ef9b7f4db8a6a2fSenpo Hu mActiveBar.setVisibility(View.VISIBLE); 13482fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague } 13582fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague 13659345144c4bde59b81bb19c95cdd977c1d1a9cd4Spike Sprague public void setMainBar(int b) { 13759345144c4bde59b81bb19c95cdd977c1d1a9cd4Spike Sprague for (int i = 0; i < getChildCount(); i++) { 13859345144c4bde59b81bb19c95cdd977c1d1a9cd4Spike Sprague getChildAt(i).setVisibility(View.INVISIBLE); 13982fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague } 14059345144c4bde59b81bb19c95cdd977c1d1a9cd4Spike Sprague switch (b) { 14159345144c4bde59b81bb19c95cdd977c1d1a9cd4Spike Sprague case BAR_STANDARD: 14259345144c4bde59b81bb19c95cdd977c1d1a9cd4Spike Sprague mMainBar = mActiveBar = mModeOptionsButtons; 14359345144c4bde59b81bb19c95cdd977c1d1a9cd4Spike Sprague break; 14459345144c4bde59b81bb19c95cdd977c1d1a9cd4Spike Sprague case BAR_PANO: 14559345144c4bde59b81bb19c95cdd977c1d1a9cd4Spike Sprague mMainBar = mActiveBar = mModeOptionsPano; 14659345144c4bde59b81bb19c95cdd977c1d1a9cd4Spike Sprague break; 14759345144c4bde59b81bb19c95cdd977c1d1a9cd4Spike Sprague } 14859345144c4bde59b81bb19c95cdd977c1d1a9cd4Spike Sprague mMainBar.setVisibility(View.VISIBLE); 14959345144c4bde59b81bb19c95cdd977c1d1a9cd4Spike Sprague } 15082fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague 15159345144c4bde59b81bb19c95cdd977c1d1a9cd4Spike Sprague public int getMainBar() { 15259345144c4bde59b81bb19c95cdd977c1d1a9cd4Spike Sprague if (mMainBar == mModeOptionsButtons) { 15359345144c4bde59b81bb19c95cdd977c1d1a9cd4Spike Sprague return BAR_STANDARD; 15459345144c4bde59b81bb19c95cdd977c1d1a9cd4Spike Sprague } 15559345144c4bde59b81bb19c95cdd977c1d1a9cd4Spike Sprague if (mMainBar == mModeOptionsPano) { 15659345144c4bde59b81bb19c95cdd977c1d1a9cd4Spike Sprague return BAR_PANO; 15759345144c4bde59b81bb19c95cdd977c1d1a9cd4Spike Sprague } 15859345144c4bde59b81bb19c95cdd977c1d1a9cd4Spike Sprague return BAR_INVALID; 15982fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague } 16082fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague 161abf54e2994961395a0feb0b08353e62718443f23Spike Sprague @Override 162abf54e2994961395a0feb0b08353e62718443f23Spike Sprague public void onWindowVisibilityChanged(int visibility) { 163abf54e2994961395a0feb0b08353e62718443f23Spike Sprague super.onWindowVisibilityChanged(visibility); 164abf54e2994961395a0feb0b08353e62718443f23Spike Sprague if (visibility != VISIBLE && !mIsHiddenOrHiding) { 165abf54e2994961395a0feb0b08353e62718443f23Spike Sprague // Collapse mode options when window is not visible. 166abf54e2994961395a0feb0b08353e62718443f23Spike Sprague setVisibility(INVISIBLE); 16759345144c4bde59b81bb19c95cdd977c1d1a9cd4Spike Sprague if (mMainBar != null) { 16859345144c4bde59b81bb19c95cdd977c1d1a9cd4Spike Sprague mMainBar.setVisibility(VISIBLE); 16959345144c4bde59b81bb19c95cdd977c1d1a9cd4Spike Sprague } 17059345144c4bde59b81bb19c95cdd977c1d1a9cd4Spike Sprague if (mActiveBar != null && mActiveBar != mMainBar) { 17159345144c4bde59b81bb19c95cdd977c1d1a9cd4Spike Sprague mActiveBar.setVisibility(INVISIBLE); 172abf54e2994961395a0feb0b08353e62718443f23Spike Sprague } 173abf54e2994961395a0feb0b08353e62718443f23Spike Sprague if (mViewToShowHide != null) { 174abf54e2994961395a0feb0b08353e62718443f23Spike Sprague mViewToShowHide.setVisibility(VISIBLE); 175abf54e2994961395a0feb0b08353e62718443f23Spike Sprague } 176abf54e2994961395a0feb0b08353e62718443f23Spike Sprague mIsHiddenOrHiding = true; 177abf54e2994961395a0feb0b08353e62718443f23Spike Sprague } 178abf54e2994961395a0feb0b08353e62718443f23Spike Sprague } 179abf54e2994961395a0feb0b08353e62718443f23Spike Sprague 18082fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague @Override 18182fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague public void onLayout(boolean changed, int left, int top, int right, int bottom) { 18282fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague if (changed) { 18382fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague mIsPortrait = (getResources().getConfiguration().orientation == 18482fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague Configuration.ORIENTATION_PORTRAIT); 18582fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague 18682fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague int buttonSize = getResources() 18782fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague .getDimensionPixelSize(R.dimen.option_button_circle_size); 18882fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague int buttonPadding = getResources() 18982fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague .getDimensionPixelSize(R.dimen.mode_options_toggle_padding); 19082fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague 19182fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague float rLeft, rRight, rTop, rBottom; 19282fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague if (mIsPortrait) { 19382fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague rLeft = getWidth() - buttonPadding - buttonSize; 19482fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague rTop = (getHeight() - buttonSize) / 2.0f; 19582fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague } else { 19682fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague rLeft = buttonPadding; 19782fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague rTop = buttonPadding; 19882fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague } 19982fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague rRight = rLeft + buttonSize; 20082fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague rBottom = rTop + buttonSize; 20182fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague mAnimateFrom.set(rLeft, rTop, rRight, rBottom); 20282fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague 20382fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague setupAnimators(); 20418b22b5963e8871e539edf669d96862eec72bb5dSpike Sprague setupToggleButtonParams(); 20582fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague } 20682fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague 20782fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague super.onLayout(changed, left, top, right, bottom); 20882fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague } 20982fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague 21082fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague @Override 21182fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague public void onDraw(Canvas canvas) { 21282fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague if (mDrawCircle) { 2134df915872c25fe61640a94c7a2c5f27eee1a1048Doris Liu canvas.drawCircle(mAnimateFrom.centerX(), mAnimateFrom.centerY(), mRadius, mPaint); 21482fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague } else if (mFill) { 21582fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague canvas.drawPaint(mPaint); 21682fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague } 21782fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague super.onDraw(canvas); 21882fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague } 21982fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague 22018b22b5963e8871e539edf669d96862eec72bb5dSpike Sprague private void setupToggleButtonParams() { 22118b22b5963e8871e539edf669d96862eec72bb5dSpike Sprague int size = (mIsPortrait ? getHeight() : getWidth()); 22218b22b5963e8871e539edf669d96862eec72bb5dSpike Sprague 22318b22b5963e8871e539edf669d96862eec72bb5dSpike Sprague for (int i = 0; i < mModeOptionsButtons.getChildCount(); i++) { 22418b22b5963e8871e539edf669d96862eec72bb5dSpike Sprague View button = mModeOptionsButtons.getChildAt(i); 22518b22b5963e8871e539edf669d96862eec72bb5dSpike Sprague if (button instanceof MultiToggleImageButton) { 22618b22b5963e8871e539edf669d96862eec72bb5dSpike Sprague MultiToggleImageButton toggleButton = (MultiToggleImageButton) button; 22718b22b5963e8871e539edf669d96862eec72bb5dSpike Sprague toggleButton.setParentSize(size); 22818b22b5963e8871e539edf669d96862eec72bb5dSpike Sprague toggleButton.setAnimDirection(mIsPortrait ? 22918b22b5963e8871e539edf669d96862eec72bb5dSpike Sprague MultiToggleImageButton.ANIM_DIRECTION_VERTICAL : 23018b22b5963e8871e539edf669d96862eec72bb5dSpike Sprague MultiToggleImageButton.ANIM_DIRECTION_HORIZONTAL); 23118b22b5963e8871e539edf669d96862eec72bb5dSpike Sprague } 23218b22b5963e8871e539edf669d96862eec72bb5dSpike Sprague } 23318b22b5963e8871e539edf669d96862eec72bb5dSpike Sprague } 23418b22b5963e8871e539edf669d96862eec72bb5dSpike Sprague 23582fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague private void setupAnimators() { 236fd29a841a046c6a02306adc9e4df1a5eeb466f39Spike Sprague if (mVisibleAnimator != null) { 237fd29a841a046c6a02306adc9e4df1a5eeb466f39Spike Sprague mVisibleAnimator.end(); 238fd29a841a046c6a02306adc9e4df1a5eeb466f39Spike Sprague } 239fd29a841a046c6a02306adc9e4df1a5eeb466f39Spike Sprague if (mHiddenAnimator != null) { 240fd29a841a046c6a02306adc9e4df1a5eeb466f39Spike Sprague mHiddenAnimator.end(); 241fd29a841a046c6a02306adc9e4df1a5eeb466f39Spike Sprague } 242fd29a841a046c6a02306adc9e4df1a5eeb466f39Spike Sprague 24382fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague final float fullSize = (mIsPortrait ? (float) getWidth() : (float) getHeight()); 24482fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague 24582fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague // show 24682fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague { 24782fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague final ValueAnimator radiusAnimator = 24882fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague ValueAnimator.ofFloat(mAnimateFrom.width()/2.0f, 24982fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague fullSize-mAnimateFrom.width()/2.0f); 25082fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague radiusAnimator.setDuration(RADIUS_ANIMATION_TIME); 25182fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague radiusAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 25282fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague @Override 25382fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague public void onAnimationUpdate(ValueAnimator animation) { 2544df915872c25fe61640a94c7a2c5f27eee1a1048Doris Liu mRadius = (Float) animation.getAnimatedValue(); 25582fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague mDrawCircle = true; 25682fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague mFill = false; 25782fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague } 25882fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague }); 25982fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague radiusAnimator.addListener(new AnimatorListenerAdapter() { 26082fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague @Override 26182fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague public void onAnimationEnd(Animator animation) { 26282fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague mDrawCircle = false; 26382fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague mFill = true; 26482fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague } 26582fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague }); 26682fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague 26756d43cf80d40379d57ac1db697bc014d5c321b91Spike Sprague final ValueAnimator alphaAnimator = ValueAnimator.ofFloat(0.0f, 1.0f); 26882fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague alphaAnimator.setDuration(SHOW_ALPHA_ANIMATION_TIME); 26982fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague alphaAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 27082fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague @Override 27182fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague public void onAnimationUpdate(ValueAnimator animation) { 27259345144c4bde59b81bb19c95cdd977c1d1a9cd4Spike Sprague mActiveBar.setAlpha((Float) animation.getAnimatedValue()); 27382fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague } 27482fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague }); 27582fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague alphaAnimator.addListener(new AnimatorListenerAdapter() { 27682fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague @Override 27782fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague public void onAnimationEnd(Animator animation) { 27859345144c4bde59b81bb19c95cdd977c1d1a9cd4Spike Sprague mActiveBar.setAlpha(1.0f); 27982fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague } 28082fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague }); 28182fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague 28256d43cf80d40379d57ac1db697bc014d5c321b91Spike Sprague final int deltaX = getResources() 28356d43cf80d40379d57ac1db697bc014d5c321b91Spike Sprague .getDimensionPixelSize(R.dimen.mode_options_buttons_anim_delta_x); 28459345144c4bde59b81bb19c95cdd977c1d1a9cd4Spike Sprague int childCount = mActiveBar.getChildCount(); 28556d43cf80d40379d57ac1db697bc014d5c321b91Spike Sprague ArrayList<Animator> paddingAnimators = new ArrayList<Animator>(); 28656d43cf80d40379d57ac1db697bc014d5c321b91Spike Sprague for (int i = 0; i < childCount; i++) { 28756d43cf80d40379d57ac1db697bc014d5c321b91Spike Sprague final View button; 28856d43cf80d40379d57ac1db697bc014d5c321b91Spike Sprague if (mIsPortrait) { 28959345144c4bde59b81bb19c95cdd977c1d1a9cd4Spike Sprague button = mActiveBar.getChildAt(i); 29056d43cf80d40379d57ac1db697bc014d5c321b91Spike Sprague } else { 29159345144c4bde59b81bb19c95cdd977c1d1a9cd4Spike Sprague button = mActiveBar.getChildAt(childCount-1-i); 29282fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague } 29382fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague 29459345144c4bde59b81bb19c95cdd977c1d1a9cd4Spike Sprague final ValueAnimator paddingAnimator = 29518b22b5963e8871e539edf669d96862eec72bb5dSpike Sprague ValueAnimator.ofFloat(deltaX*(childCount-i), 0.0f); 29659345144c4bde59b81bb19c95cdd977c1d1a9cd4Spike Sprague paddingAnimator.setDuration(PADDING_ANIMATION_TIME); 29759345144c4bde59b81bb19c95cdd977c1d1a9cd4Spike Sprague paddingAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 29859345144c4bde59b81bb19c95cdd977c1d1a9cd4Spike Sprague @Override 29959345144c4bde59b81bb19c95cdd977c1d1a9cd4Spike Sprague public void onAnimationUpdate(ValueAnimator animation) { 30059345144c4bde59b81bb19c95cdd977c1d1a9cd4Spike Sprague if (mIsPortrait) { 30159345144c4bde59b81bb19c95cdd977c1d1a9cd4Spike Sprague button.setTranslationX((Float) animation.getAnimatedValue()); 30259345144c4bde59b81bb19c95cdd977c1d1a9cd4Spike Sprague } else { 30359345144c4bde59b81bb19c95cdd977c1d1a9cd4Spike Sprague button.setTranslationY(-((Float) animation.getAnimatedValue())); 30456d43cf80d40379d57ac1db697bc014d5c321b91Spike Sprague } 30559345144c4bde59b81bb19c95cdd977c1d1a9cd4Spike Sprague invalidate(); 30659345144c4bde59b81bb19c95cdd977c1d1a9cd4Spike Sprague } 30759345144c4bde59b81bb19c95cdd977c1d1a9cd4Spike Sprague }); 30856d43cf80d40379d57ac1db697bc014d5c321b91Spike Sprague 30959345144c4bde59b81bb19c95cdd977c1d1a9cd4Spike Sprague paddingAnimators.add(paddingAnimator); 31056d43cf80d40379d57ac1db697bc014d5c321b91Spike Sprague } 31159345144c4bde59b81bb19c95cdd977c1d1a9cd4Spike Sprague 31256d43cf80d40379d57ac1db697bc014d5c321b91Spike Sprague AnimatorSet paddingAnimatorSet = new AnimatorSet(); 31356d43cf80d40379d57ac1db697bc014d5c321b91Spike Sprague paddingAnimatorSet.playTogether(paddingAnimators); 31482fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague 31582fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague mVisibleAnimator = new AnimatorSet(); 31682fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague mVisibleAnimator.setInterpolator(Gusterpolator.INSTANCE); 31756d43cf80d40379d57ac1db697bc014d5c321b91Spike Sprague mVisibleAnimator.playTogether(radiusAnimator, alphaAnimator, paddingAnimatorSet); 31882fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague } 31982fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague 32082fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague // hide 32182fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague { 32282fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague final ValueAnimator radiusAnimator = 32382fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague ValueAnimator.ofFloat(fullSize-mAnimateFrom.width()/2.0f, 32482fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague mAnimateFrom.width()/2.0f); 32582fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague radiusAnimator.setDuration(RADIUS_ANIMATION_TIME); 32682fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague radiusAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 32782fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague @Override 32882fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague public void onAnimationUpdate(ValueAnimator animation) { 3294df915872c25fe61640a94c7a2c5f27eee1a1048Doris Liu mRadius = (Float) animation.getAnimatedValue(); 33082fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague mDrawCircle = true; 33182fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague mFill = false; 33282fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague invalidate(); 33382fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague } 33482fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague }); 33582fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague radiusAnimator.addListener(new AnimatorListenerAdapter() { 33682fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague @Override 33782fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague public void onAnimationEnd(Animator animation) { 33882fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague if (mViewToShowHide != null) { 33982fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague mViewToShowHide.setVisibility(View.VISIBLE); 34082fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague mDrawCircle = false; 34182fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague mFill = false; 34282fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague invalidate(); 34382fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague } 34482fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague } 34582fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague }); 34682fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague 34782fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague final ValueAnimator alphaAnimator = ValueAnimator.ofFloat(1.0f, 0.0f); 34882fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague alphaAnimator.setDuration(HIDE_ALPHA_ANIMATION_TIME); 34982fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague alphaAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 35082fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague @Override 35182fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague public void onAnimationUpdate(ValueAnimator animation) { 35259345144c4bde59b81bb19c95cdd977c1d1a9cd4Spike Sprague mActiveBar.setAlpha((Float) animation.getAnimatedValue()); 35382fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague invalidate(); 35482fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague } 35582fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague }); 35682fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague alphaAnimator.addListener(new AnimatorListenerAdapter() { 35782fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague @Override 35882fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague public void onAnimationEnd(Animator animation) { 3592a58938576e6d4220c02cf0b9a8226a1d3bcf176Spike Sprague setVisibility(View.INVISIBLE); 36059345144c4bde59b81bb19c95cdd977c1d1a9cd4Spike Sprague if (mActiveBar != mMainBar) { 36159345144c4bde59b81bb19c95cdd977c1d1a9cd4Spike Sprague mActiveBar.setAlpha(1.0f); 36259345144c4bde59b81bb19c95cdd977c1d1a9cd4Spike Sprague mActiveBar.setVisibility(View.INVISIBLE); 36359345144c4bde59b81bb19c95cdd977c1d1a9cd4Spike Sprague } 36459345144c4bde59b81bb19c95cdd977c1d1a9cd4Spike Sprague mMainBar.setAlpha(1.0f); 36559345144c4bde59b81bb19c95cdd977c1d1a9cd4Spike Sprague mMainBar.setVisibility(View.VISIBLE); 36659345144c4bde59b81bb19c95cdd977c1d1a9cd4Spike Sprague mActiveBar = mMainBar; 36782fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague invalidate(); 36882fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague } 36982fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague }); 37082fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague 37182fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague mHiddenAnimator = new AnimatorSet(); 37282fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague mHiddenAnimator.setInterpolator(Gusterpolator.INSTANCE); 37382fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague mHiddenAnimator.playTogether(radiusAnimator, alphaAnimator); 37482fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague } 37582fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague } 37682fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague 37782fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague public void animateVisible() { 378591eec6465d29bbc053e164071c4c3a7c260a1d3Spike Sprague if (mIsHiddenOrHiding) { 379591eec6465d29bbc053e164071c4c3a7c260a1d3Spike Sprague if (mViewToShowHide != null) { 380591eec6465d29bbc053e164071c4c3a7c260a1d3Spike Sprague mViewToShowHide.setVisibility(View.INVISIBLE); 381591eec6465d29bbc053e164071c4c3a7c260a1d3Spike Sprague } 382591eec6465d29bbc053e164071c4c3a7c260a1d3Spike Sprague mHiddenAnimator.cancel(); 383591eec6465d29bbc053e164071c4c3a7c260a1d3Spike Sprague mVisibleAnimator.end(); 3842a58938576e6d4220c02cf0b9a8226a1d3bcf176Spike Sprague setVisibility(View.VISIBLE); 385591eec6465d29bbc053e164071c4c3a7c260a1d3Spike Sprague mVisibleAnimator.start(); 38654ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu if (mListener.isPresent()) { 38754ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu mListener.get().onBeginToShowModeOptions(); 38854ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu } 38982fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague } 390591eec6465d29bbc053e164071c4c3a7c260a1d3Spike Sprague mIsHiddenOrHiding = false; 39182fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague } 39282fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague 39382fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague public void animateHidden() { 394591eec6465d29bbc053e164071c4c3a7c260a1d3Spike Sprague if (!mIsHiddenOrHiding) { 395591eec6465d29bbc053e164071c4c3a7c260a1d3Spike Sprague mVisibleAnimator.cancel(); 396591eec6465d29bbc053e164071c4c3a7c260a1d3Spike Sprague mHiddenAnimator.end(); 397591eec6465d29bbc053e164071c4c3a7c260a1d3Spike Sprague mHiddenAnimator.start(); 39854ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu if (mListener.isPresent()) { 39954ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu mListener.get().onBeginToHideModeOptions(); 40054ac03ba6ae3e739df74c6d9e35fda9017be07d7Senpo Hu } 401591eec6465d29bbc053e164071c4c3a7c260a1d3Spike Sprague } 402591eec6465d29bbc053e164071c4c3a7c260a1d3Spike Sprague mIsHiddenOrHiding = true; 40382fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague } 40482fa6ae85f7c07fef480eb1cd0cf7f578b150676Spike Sprague}