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