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 ActionBar getActionBar();
     50     }
     51 
     52     public ActionBarController(ActivityUi activityUi, SearchEditTextLayout searchBox) {
     53         mActivityUi = activityUi;
     54         mSearchBox = searchBox;
     55     }
     56 
     57     /**
     58      * @return Whether or not the action bar is currently showing (both slid down and visible)
     59      */
     60     public boolean isActionBarShowing() {
     61         return !mIsActionBarSlidUp && !mSearchBox.isFadedOut();
     62     }
     63 
     64     /**
     65      * Called when the user has tapped on the collapsed search box, to start a new search query.
     66      */
     67     public void onSearchBoxTapped() {
     68         if (DEBUG) {
     69             Log.d(TAG, "OnSearchBoxTapped: isInSearchUi " + mActivityUi.isInSearchUi());
     70         }
     71         if (!mActivityUi.isInSearchUi()) {
     72             mSearchBox.expand(true /* animate */, true /* requestFocus */);
     73         }
     74     }
     75 
     76     /**
     77      * Called when search UI has been exited for some reason.
     78      */
     79     public void onSearchUiExited() {
     80         if (DEBUG) {
     81             Log.d(TAG, "OnSearchUIExited: isExpanded " + mSearchBox.isExpanded()
     82                     + " isFadedOut: " + mSearchBox.isFadedOut()
     83                     + " shouldShowActionBar: " + mActivityUi.shouldShowActionBar());
     84         }
     85         if (mSearchBox.isExpanded()) {
     86             mSearchBox.collapse(true /* animate */);
     87         }
     88         if (mSearchBox.isFadedOut()) {
     89             mSearchBox.fadeIn();
     90         }
     91 
     92         if (mActivityUi.shouldShowActionBar()) {
     93             slideActionBar(false /* slideUp */, false /* animate */);
     94         } else {
     95             slideActionBar(true /* slideUp */, false /* animate */);
     96         }
     97     }
     98 
     99     /**
    100      * Called to indicate that the user is trying to hide the dialpad. Should be called before
    101      * any state changes have actually occurred.
    102      */
    103     public void onDialpadDown() {
    104         if (DEBUG) {
    105             Log.d(TAG, "OnDialpadDown: isInSearchUi " + mActivityUi.isInSearchUi()
    106                     + " hasSearchQuery: " + mActivityUi.hasSearchQuery()
    107                     + " isFadedOut: " + mSearchBox.isFadedOut()
    108                     + " isExpanded: " + mSearchBox.isExpanded());
    109         }
    110         if (mActivityUi.isInSearchUi()) {
    111             if (mActivityUi.hasSearchQuery()) {
    112                 if (mSearchBox.isFadedOut()) {
    113                     mSearchBox.setVisible(true);
    114                 }
    115                 if (!mSearchBox.isExpanded()) {
    116                     mSearchBox.expand(false /* animate */, false /* requestFocus */);
    117                 }
    118                 slideActionBar(false /* slideUp */, true /* animate */);
    119             } else {
    120                 mSearchBox.fadeIn();
    121             }
    122         }
    123     }
    124 
    125     /**
    126      * Called to indicate that the user is trying to show the dialpad. Should be called before
    127      * any state changes have actually occurred.
    128      */
    129     public void onDialpadUp() {
    130         if (DEBUG) {
    131             Log.d(TAG, "OnDialpadUp: isInSearchUi " + mActivityUi.isInSearchUi());
    132         }
    133         if (mActivityUi.isInSearchUi()) {
    134             slideActionBar(true /* slideUp */, true /* animate */);
    135         } else {
    136             // From the lists fragment
    137             mSearchBox.fadeOut(mFadeOutCallback);
    138         }
    139     }
    140 
    141     public void slideActionBar(boolean slideUp, boolean animate) {
    142         if (DEBUG) {
    143             Log.d(TAG, "Sliding actionBar - up: " + slideUp + " animate: " + animate);
    144         }
    145         if (animate) {
    146             ValueAnimator animator =
    147                     slideUp ? ValueAnimator.ofFloat(0, 1) : ValueAnimator.ofFloat(1, 0);
    148             animator.addUpdateListener(new AnimatorUpdateListener() {
    149                 @Override
    150                 public void onAnimationUpdate(ValueAnimator animation) {
    151                     final float value = (float) animation.getAnimatedValue();
    152                     setHideOffset(
    153                             (int) (mActivityUi.getActionBarHeight() * value));
    154                 }
    155             });
    156             animator.start();
    157         } else {
    158            setHideOffset(slideUp ? mActivityUi.getActionBarHeight() : 0);
    159         }
    160         mIsActionBarSlidUp = slideUp;
    161     }
    162 
    163     public void setAlpha(float alphaValue) {
    164         mSearchBox.animate().alpha(alphaValue).start();
    165     }
    166 
    167     public void setHideOffset(int offset) {
    168         mIsActionBarSlidUp = offset >= mActivityUi.getActionBarHeight();
    169         mActivityUi.getActionBar().setHideOffset(offset);
    170     }
    171 
    172     /**
    173      * @return The offset the action bar is being translated upwards by
    174      */
    175     public int getHideOffset() {
    176         return mActivityUi.getActionBar().getHideOffset();
    177     }
    178 
    179     /**
    180      * Saves the current state of the action bar into a provided {@link Bundle}
    181      */
    182     public void saveInstanceState(Bundle outState) {
    183         outState.putBoolean(KEY_IS_SLID_UP, mIsActionBarSlidUp);
    184         outState.putBoolean(KEY_IS_FADED_OUT, mSearchBox.isFadedOut());
    185         outState.putBoolean(KEY_IS_EXPANDED, mSearchBox.isExpanded());
    186     }
    187 
    188     /**
    189      * Restores the action bar state from a provided {@link Bundle}.
    190      */
    191     public void restoreInstanceState(Bundle inState) {
    192         mIsActionBarSlidUp = inState.getBoolean(KEY_IS_SLID_UP);
    193 
    194         final boolean isSearchBoxFadedOut = inState.getBoolean(KEY_IS_FADED_OUT);
    195         if (isSearchBoxFadedOut) {
    196             if (!mSearchBox.isFadedOut()) {
    197                 mSearchBox.setVisible(false);
    198             }
    199         } else if (mSearchBox.isFadedOut()) {
    200                 mSearchBox.setVisible(true);
    201         }
    202 
    203         final boolean isSearchBoxExpanded = inState.getBoolean(KEY_IS_EXPANDED);
    204         if (isSearchBoxExpanded) {
    205             if (!mSearchBox.isExpanded()) {
    206                 mSearchBox.expand(false, false);
    207             }
    208         } else if (mSearchBox.isExpanded()) {
    209                 mSearchBox.collapse(false);
    210         }
    211     }
    212 
    213     /**
    214      * This should be called after onCreateOptionsMenu has been called, when the actionbar has
    215      * been laid out and actually has a height.
    216      */
    217     public void restoreActionBarOffset() {
    218         slideActionBar(mIsActionBarSlidUp /* slideUp */, false /* animate */);
    219     }
    220 
    221     @VisibleForTesting
    222     public boolean getIsActionBarSlidUp() {
    223         return mIsActionBarSlidUp;
    224     }
    225 }
    226