ActionBarController.java revision ccca31529c07970e89419fb85a9e8153a5396838
1/* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16package com.android.dialer.app.widget; 17 18import android.animation.ValueAnimator; 19import android.animation.ValueAnimator.AnimatorUpdateListener; 20import android.os.Bundle; 21import android.support.annotation.VisibleForTesting; 22import android.util.Log; 23import com.android.dialer.animation.AnimUtils.AnimationCallback; 24import com.android.dialer.app.DialtactsActivity; 25 26/** 27 * Controls the various animated properties of the actionBar: showing/hiding, fading/revealing, and 28 * collapsing/expanding, and assigns suitable properties to the actionBar based on the current state 29 * of the UI. 30 */ 31public class ActionBarController { 32 33 public static final boolean DEBUG = DialtactsActivity.DEBUG; 34 public static final String TAG = "ActionBarController"; 35 private static final String KEY_IS_SLID_UP = "key_actionbar_is_slid_up"; 36 private static final String KEY_IS_FADED_OUT = "key_actionbar_is_faded_out"; 37 private static final String KEY_IS_EXPANDED = "key_actionbar_is_expanded"; 38 39 private ActivityUi mActivityUi; 40 private SearchEditTextLayout mSearchBox; 41 42 private boolean mIsActionBarSlidUp; 43 44 private final AnimationCallback mFadeOutCallback = 45 new AnimationCallback() { 46 @Override 47 public void onAnimationEnd() { 48 slideActionBar(true /* slideUp */, false /* animate */); 49 } 50 51 @Override 52 public void onAnimationCancel() { 53 slideActionBar(true /* slideUp */, false /* animate */); 54 } 55 }; 56 57 public ActionBarController(ActivityUi activityUi, SearchEditTextLayout searchBox) { 58 mActivityUi = activityUi; 59 mSearchBox = searchBox; 60 } 61 62 /** @return Whether or not the action bar is currently showing (both slid down and visible) */ 63 public boolean isActionBarShowing() { 64 return !mIsActionBarSlidUp && !mSearchBox.isFadedOut(); 65 } 66 67 /** Called when the user has tapped on the collapsed search box, to start a new search query. */ 68 public void onSearchBoxTapped() { 69 if (DEBUG) { 70 Log.d(TAG, "OnSearchBoxTapped: isInSearchUi " + mActivityUi.isInSearchUi()); 71 } 72 if (!mActivityUi.isInSearchUi()) { 73 mSearchBox.expand(true /* animate */, true /* requestFocus */); 74 } 75 } 76 77 /** Called when search UI has been exited for some reason. */ 78 public void onSearchUiExited() { 79 if (DEBUG) { 80 Log.d( 81 TAG, 82 "OnSearchUIExited: isExpanded " 83 + mSearchBox.isExpanded() 84 + " isFadedOut: " 85 + mSearchBox.isFadedOut() 86 + " shouldShowActionBar: " 87 + mActivityUi.shouldShowActionBar()); 88 } 89 if (mSearchBox.isExpanded()) { 90 mSearchBox.collapse(true /* animate */); 91 } 92 if (mSearchBox.isFadedOut()) { 93 mSearchBox.fadeIn(); 94 } 95 96 if (mActivityUi.shouldShowActionBar()) { 97 slideActionBar(false /* slideUp */, false /* animate */); 98 } else { 99 slideActionBar(true /* slideUp */, false /* animate */); 100 } 101 } 102 103 /** 104 * Called to indicate that the user is trying to hide the dialpad. Should be called before any 105 * state changes have actually occurred. 106 */ 107 public void onDialpadDown() { 108 if (DEBUG) { 109 Log.d( 110 TAG, 111 "OnDialpadDown: isInSearchUi " 112 + mActivityUi.isInSearchUi() 113 + " hasSearchQuery: " 114 + mActivityUi.hasSearchQuery() 115 + " isFadedOut: " 116 + mSearchBox.isFadedOut() 117 + " isExpanded: " 118 + mSearchBox.isExpanded()); 119 } 120 if (mActivityUi.isInSearchUi()) { 121 if (mActivityUi.hasSearchQuery()) { 122 if (mSearchBox.isFadedOut()) { 123 mSearchBox.setVisible(true); 124 } 125 if (!mSearchBox.isExpanded()) { 126 mSearchBox.expand(false /* animate */, false /* requestFocus */); 127 } 128 slideActionBar(false /* slideUp */, true /* animate */); 129 } else { 130 mSearchBox.fadeIn(); 131 } 132 } 133 } 134 135 /** 136 * Called to indicate that the user is trying to show the dialpad. Should be called before any 137 * state changes have actually occurred. 138 */ 139 public void onDialpadUp() { 140 if (DEBUG) { 141 Log.d(TAG, "OnDialpadUp: isInSearchUi " + mActivityUi.isInSearchUi()); 142 } 143 if (mActivityUi.isInSearchUi()) { 144 slideActionBar(true /* slideUp */, true /* animate */); 145 } else { 146 // From the lists fragment 147 mSearchBox.fadeOut(mFadeOutCallback); 148 } 149 } 150 151 public void slideActionBar(boolean slideUp, boolean animate) { 152 if (DEBUG) { 153 Log.d(TAG, "Sliding actionBar - up: " + slideUp + " animate: " + animate); 154 } 155 if (animate) { 156 ValueAnimator animator = slideUp ? ValueAnimator.ofFloat(0, 1) : ValueAnimator.ofFloat(1, 0); 157 animator.addUpdateListener( 158 new AnimatorUpdateListener() { 159 @Override 160 public void onAnimationUpdate(ValueAnimator animation) { 161 final float value = (float) animation.getAnimatedValue(); 162 setHideOffset((int) (mActivityUi.getActionBarHeight() * value)); 163 } 164 }); 165 animator.start(); 166 } else { 167 setHideOffset(slideUp ? mActivityUi.getActionBarHeight() : 0); 168 } 169 mIsActionBarSlidUp = slideUp; 170 } 171 172 public void setAlpha(float alphaValue) { 173 mSearchBox.animate().alpha(alphaValue).start(); 174 } 175 176 /** @return The offset the action bar is being translated upwards by */ 177 public int getHideOffset() { 178 return mActivityUi.getActionBarHideOffset(); 179 } 180 181 public void setHideOffset(int offset) { 182 mIsActionBarSlidUp = offset >= mActivityUi.getActionBarHeight(); 183 mActivityUi.setActionBarHideOffset(offset); 184 } 185 186 public int getActionBarHeight() { 187 return mActivityUi.getActionBarHeight(); 188 } 189 190 /** Saves the current state of the action bar into a provided {@link Bundle} */ 191 public void saveInstanceState(Bundle outState) { 192 outState.putBoolean(KEY_IS_SLID_UP, mIsActionBarSlidUp); 193 outState.putBoolean(KEY_IS_FADED_OUT, mSearchBox.isFadedOut()); 194 outState.putBoolean(KEY_IS_EXPANDED, mSearchBox.isExpanded()); 195 } 196 197 /** Restores the action bar state from a provided {@link Bundle}. */ 198 public void restoreInstanceState(Bundle inState) { 199 mIsActionBarSlidUp = inState.getBoolean(KEY_IS_SLID_UP); 200 201 final boolean isSearchBoxFadedOut = inState.getBoolean(KEY_IS_FADED_OUT); 202 if (isSearchBoxFadedOut) { 203 if (!mSearchBox.isFadedOut()) { 204 mSearchBox.setVisible(false); 205 } 206 } else if (mSearchBox.isFadedOut()) { 207 mSearchBox.setVisible(true); 208 } 209 210 final boolean isSearchBoxExpanded = inState.getBoolean(KEY_IS_EXPANDED); 211 if (isSearchBoxExpanded) { 212 if (!mSearchBox.isExpanded()) { 213 mSearchBox.expand(false, false); 214 } 215 } else if (mSearchBox.isExpanded()) { 216 mSearchBox.collapse(false); 217 } 218 } 219 220 /** 221 * This should be called after onCreateOptionsMenu has been called, when the actionbar has been 222 * laid out and actually has a height. 223 */ 224 public void restoreActionBarOffset() { 225 slideActionBar(mIsActionBarSlidUp /* slideUp */, false /* animate */); 226 } 227 228 @VisibleForTesting 229 public boolean getIsActionBarSlidUp() { 230 return mIsActionBarSlidUp; 231 } 232 233 public interface ActivityUi { 234 235 boolean isInSearchUi(); 236 237 boolean hasSearchQuery(); 238 239 boolean shouldShowActionBar(); 240 241 int getActionBarHeight(); 242 243 int getActionBarHideOffset(); 244 245 void setActionBarHideOffset(int offset); 246 } 247} 248