Merge "Fix FAB state and transitions." into mnc-dev
diff --git a/src/com/android/dialer/DialtactsActivity.java b/src/com/android/dialer/DialtactsActivity.java
index 47e5234..fc0f1fb 100644
--- a/src/com/android/dialer/DialtactsActivity.java
+++ b/src/com/android/dialer/DialtactsActivity.java
@@ -84,7 +84,7 @@
 import com.android.dialer.util.DialerUtils;
 import com.android.dialer.widget.ActionBarController;
 import com.android.dialer.widget.SearchEditTextLayout;
-import com.android.dialer.widget.SearchEditTextLayout.OnBackButtonClickedListener;
+import com.android.dialer.widget.SearchEditTextLayout.Callback;
 import com.android.dialerbind.DatabaseHelperManager;
 import com.android.phone.common.animation.AnimUtils;
 import com.android.phone.common.animation.AnimationListenerAdapter;
@@ -136,6 +136,8 @@
 
     private static final int ACTIVITY_REQUEST_CODE_VOICE_SEARCH = 1;
 
+    private static final int FAB_SCALE_IN_DELAY_MS = 300;
+
     private FrameLayout mParentLayout;
 
     /**
@@ -338,14 +340,19 @@
     };
 
     /**
-     * If the search term is empty and the user closes the soft keyboard, close the search UI.
+     * Handles the user closing the soft keyboard.
      */
     private final View.OnKeyListener mSearchEditTextLayoutListener = new View.OnKeyListener() {
         @Override
         public boolean onKey(View v, int keyCode, KeyEvent event) {
-            if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_DOWN &&
-                    TextUtils.isEmpty(mSearchView.getText().toString())) {
-                maybeExitSearchUi();
+            if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_DOWN) {
+                if (TextUtils.isEmpty(mSearchView.getText().toString())) {
+                    // If the search term is empty, close the search UI.
+                    maybeExitSearchUi();
+                } else {
+                    // If the search term is not empty, show the dialpad fab.
+                    showFabInSearchUi();
+                }
             }
             return false;
         }
@@ -394,11 +401,17 @@
                 .setOnClickListener(mSearchViewOnClickListener);
         searchEditTextLayout.findViewById(R.id.search_box_start_search)
                 .setOnClickListener(mSearchViewOnClickListener);
-        searchEditTextLayout.setOnBackButtonClickedListener(new OnBackButtonClickedListener() {
+        searchEditTextLayout.setCallback(new SearchEditTextLayout.Callback() {
             @Override
             public void onBackButtonClicked() {
                 onBackPressed();
             }
+
+            @Override
+            public void onSearchViewClicked() {
+                // Hide FAB, as the keyboard is shown.
+                mFloatingActionButtonController.scaleOut();
+            }
         });
 
         mIsLandscape = getResources().getConfiguration().orientation
@@ -463,7 +476,8 @@
                         observer.removeOnGlobalLayoutListener(this);
                         int screenWidth = mParentLayout.getWidth();
                         mFloatingActionButtonController.setScreenWidth(screenWidth);
-                        updateFloatingActionButtonControllerAlignment(false /* animate */);
+                        mFloatingActionButtonController.align(
+                                getFabAlignment(), false /* animate */);
                     }
                 });
 
@@ -527,7 +541,7 @@
         }
         prepareVoiceSearchButton();
         mDialerDatabaseHelper.startSmartDialUpdateThread();
-        updateFloatingActionButtonControllerAlignment(false /* animate */);
+        mFloatingActionButtonController.align(getFabAlignment(), false /* animate */);
         Trace.endSection();
     }
 
@@ -744,7 +758,7 @@
 
         updateSearchFragmentPosition();
 
-        updateFloatingActionButtonControllerAlignment(animate);
+        mFloatingActionButtonController.align(getFabAlignment(), animate);
         if (animate) {
             mDialpadFragment.getView().startAnimation(mSlideOut);
         } else {
@@ -948,6 +962,8 @@
         mInDialpadSearch = smartDialSearch;
         mInRegularSearch = !smartDialSearch;
 
+        mFloatingActionButtonController.scaleOut();
+
         SearchFragment fragment = (SearchFragment) getFragmentManager().findFragmentByTag(tag);
         if (animate) {
             transaction.setCustomAnimations(android.R.animator.fade_in, 0);
@@ -959,6 +975,15 @@
                 fragment = new SmartDialSearchFragment();
             } else {
                 fragment = new RegularSearchFragment();
+                fragment.setOnTouchListener(new View.OnTouchListener() {
+                    @Override
+                    public boolean onTouch(View v, MotionEvent event) {
+                        // Show the FAB when the user touches the lists fragment and the soft
+                        // keyboard is hidden.
+                        showFabInSearchUi();
+                        return false;
+                    }
+                });
             }
             transaction.add(R.id.dialtacts_frame, fragment, tag);
         } else {
@@ -995,6 +1020,14 @@
 
         setNotInSearchUi();
 
+        // Restore the FAB for the lists fragment.
+        if (getFabAlignment() != FloatingActionButtonController.ALIGN_END) {
+            mFloatingActionButtonController.setVisible(false);
+        }
+        mFloatingActionButtonController.scaleIn(FAB_SCALE_IN_DELAY_MS);
+        onPageScrolled(mListsFragment.getCurrentTabIndex(), 0 /* offset */, 0 /* pixelOffset */);
+        onPageSelected(mListsFragment.getCurrentTabIndex());
+
         final FragmentTransaction transaction = getFragmentManager().beginTransaction();
         if (mSmartDialSearchFragment != null) {
             transaction.remove(mSmartDialSearchFragment);
@@ -1055,6 +1088,14 @@
         return false;
     }
 
+    private void showFabInSearchUi() {
+        mFloatingActionButtonController.changeIcon(
+                getResources().getDrawable(R.drawable.fab_ic_dial),
+                getResources().getString(R.string.action_menu_dialpad_button));
+        mFloatingActionButtonController.align(getFabAlignment(), false /* animate */);
+        mFloatingActionButtonController.scaleIn(FAB_SCALE_IN_DELAY_MS);
+    }
+
     @Override
     public void onDialpadQueryChanged(String query) {
         if (mSmartDialSearchFragment != null) {
@@ -1251,16 +1292,12 @@
         return mActionBarHeight;
     }
 
-    /**
-     * Updates controller based on currently known information.
-     *
-     * @param animate Whether or not to animate the transition.
-     */
-    private void updateFloatingActionButtonControllerAlignment(boolean animate) {
-        int align = (!mIsLandscape &&
-                mListsFragment.getCurrentTabIndex() == ListsFragment.TAB_INDEX_SPEED_DIAL) ?
-                FloatingActionButtonController.ALIGN_MIDDLE :
-                        FloatingActionButtonController.ALIGN_END;
-        mFloatingActionButtonController.align(align, 0 /* offsetX */, 0 /* offsetY */, animate);
+
+    private int getFabAlignment() {
+        if (!mIsLandscape && !isInSearchUi() &&
+                mListsFragment.getCurrentTabIndex() == ListsFragment.TAB_INDEX_SPEED_DIAL) {
+            return FloatingActionButtonController.ALIGN_MIDDLE;
+        }
+        return FloatingActionButtonController.ALIGN_END;
     }
 }
diff --git a/src/com/android/dialer/list/SearchFragment.java b/src/com/android/dialer/list/SearchFragment.java
index f86c0e5..78c3ad3 100644
--- a/src/com/android/dialer/list/SearchFragment.java
+++ b/src/com/android/dialer/list/SearchFragment.java
@@ -50,6 +50,7 @@
     private static final String TAG  = SearchFragment.class.getSimpleName();
 
     private OnListFragmentScrolledListener mActivityScrollListener;
+    private View.OnTouchListener mActivityOnTouchListener;
 
     /*
      * Stores the untouched user-entered string that is used to populate the add to contacts
@@ -123,6 +124,9 @@
                     int totalItemCount) {
             }
         });
+        if (mActivityOnTouchListener != null) {
+            listView.setOnTouchListener(mActivityOnTouchListener);
+        }
 
         updatePosition(false /* animate */);
     }
@@ -298,4 +302,8 @@
             getAdapter().setQueryString(null);
         }
     }
+
+    public void setOnTouchListener(View.OnTouchListener onTouchListener) {
+        mActivityOnTouchListener = onTouchListener;
+    }
 }
diff --git a/src/com/android/dialer/widget/SearchEditTextLayout.java b/src/com/android/dialer/widget/SearchEditTextLayout.java
index f1fa986..544749f 100644
--- a/src/com/android/dialer/widget/SearchEditTextLayout.java
+++ b/src/com/android/dialer/widget/SearchEditTextLayout.java
@@ -61,13 +61,14 @@
 
     private ValueAnimator mAnimator;
 
-    private OnBackButtonClickedListener mOnBackButtonClickedListener;
+    private Callback mCallback;
 
     /**
      * Listener for the back button next to the search view being pressed
      */
-    public interface OnBackButtonClickedListener {
+    public interface Callback {
         public void onBackButtonClicked();
+        public void onSearchViewClicked();
     }
 
     public SearchEditTextLayout(Context context, AttributeSet attrs) {
@@ -78,8 +79,8 @@
         mPreImeKeyListener = listener;
     }
 
-    public void setOnBackButtonClickedListener(OnBackButtonClickedListener listener) {
-        mOnBackButtonClickedListener = listener;
+    public void setCallback(Callback listener) {
+        mCallback = listener;
     }
 
     @Override
@@ -126,6 +127,15 @@
             }
         });
 
+        mSearchView.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                if (mCallback != null) {
+                    mCallback.onSearchViewClicked();
+                }
+            }
+        });
+
         mSearchView.addTextChangedListener(new TextWatcher() {
             @Override
             public void beforeTextChanged(CharSequence s, int start, int count, int after) {
@@ -151,8 +161,8 @@
         findViewById(R.id.search_back_button).setOnClickListener(new OnClickListener() {
             @Override
             public void onClick(View v) {
-                if (mOnBackButtonClickedListener != null) {
-                    mOnBackButtonClickedListener.onBackButtonClicked();
+                if (mCallback != null) {
+                    mCallback.onBackButtonClicked();
                 }
             }
         });