Improvements to multi select

* selection bar now uses an <- instead of X icon
* FAB animates away when entering either selection or search mode
* allow selection mode to be entered once already in search mode

Demo: https://drive.google.com/a/google.com/file/d/0B-vjphxTdjuANERMUDF6Y2NyQXc/view?usp=sharing

Bug: 19549465
Change-Id: I657bf564c8e6cdfca6f7779918c4807e09e78d9b
diff --git a/res/drawable/floating_action_button.xml b/res/drawable/floating_action_button.xml
index 34612d5..7753c89 100644
--- a/res/drawable/floating_action_button.xml
+++ b/res/drawable/floating_action_button.xml
@@ -16,6 +16,10 @@
 -->
 
 <ripple xmlns:android="http://schemas.android.com/apk/res/android"
-    android:color="@color/contacts_accent_color">
-    <item android:drawable="@drawable/fab_blue" />
-</ripple>
+     android:color="@color/contacts_accent_color">
+     <item android:id="@android:id/mask">
+          <shape android:shape="oval">
+               <solid android:color="@android:color/white" />
+          </shape>
+     </item>
+</ripple>
\ No newline at end of file
diff --git a/res/layout/floating_action_button.xml b/res/layout/floating_action_button.xml
index 1541d42..294d88b 100644
--- a/res/layout/floating_action_button.xml
+++ b/res/layout/floating_action_button.xml
@@ -22,6 +22,7 @@
     android:layout_height="@dimen/floating_action_button_height"
     android:layout_marginEnd="@dimen/floating_action_button_margin_right"
     android:layout_marginBottom="@dimen/floating_action_button_margin_bottom"
+    android:background="@drawable/fab_blue"
     android:layout_alignParentEnd="true"
     android:layout_alignParentBottom="true">
 
diff --git a/res/layout/selection_bar.xml b/res/layout/selection_bar.xml
index e6b1f66..34cdd60 100644
--- a/res/layout/selection_bar.xml
+++ b/res/layout/selection_bar.xml
@@ -24,7 +24,7 @@
         android:id="@+id/selection_close"
         android:layout_width="48dp"
         android:layout_height="48dp"
-        android:src="@drawable/ic_close_dk"
+        android:src="@drawable/ic_back_arrow"
         android:background="?android:attr/selectableItemBackgroundBorderless"
         android:contentDescription="@string/action_menu_back_from_search"
         android:layout_gravity="center_vertical|start"
diff --git a/src/com/android/contacts/activities/ActionBarAdapter.java b/src/com/android/contacts/activities/ActionBarAdapter.java
index dc9fcf2..c82c04e 100644
--- a/src/com/android/contacts/activities/ActionBarAdapter.java
+++ b/src/com/android/contacts/activities/ActionBarAdapter.java
@@ -55,6 +55,7 @@
             public static final int START_SEARCH_MODE = 1;
             public static final int START_SELECTION_MODE = 2;
             public static final int STOP_SEARCH_AND_SELECTION_MODE = 3;
+            public static final int BEGIN_STOPPING_SEARCH_AND_SELECTION_MODE = 4;
         }
 
         void onAction(int action);
@@ -347,7 +348,7 @@
         if (mShowHomeIcon && !isSearchOrSelectionMode) {
             newFlags |= ActionBar.DISPLAY_SHOW_HOME;
         }
-        if (mSearchMode) {
+        if (mSearchMode && !mSelectionMode) {
             // The search container is placed inside the toolbar. So we need to disable the
             // Toolbar's content inset in order to allow the search container to be the width of
             // the window.
@@ -384,6 +385,8 @@
 
         final boolean isSelectionModeChanging
                 = (mSelectionContainer.getParent() == null) == mSelectionMode;
+        final boolean isSwitchingFromSearchToSelection =
+                mSearchMode && isSelectionModeChanging || mSearchMode && mSelectionMode;
         final boolean isSearchModeChanging
                 = (mSearchContainer.getParent() == null) == mSearchMode;
         final boolean isTabHeightChanging = isSearchModeChanging || isSelectionModeChanging;
@@ -391,21 +394,19 @@
         // When skipAnimation=true, it is possible that we will switch from search mode
         // to selection mode directly. So we need to remove the undesired container in addition
         // to adding the desired container.
-        if (skipAnimation) {
-            if (isTabHeightChanging) {
+        if (skipAnimation || isSwitchingFromSearchToSelection) {
+            if (isTabHeightChanging || isSwitchingFromSearchToSelection) {
                 mToolbar.removeView(mLandscapeTabs);
-                if (mSearchMode) {
+                mToolbar.removeView(mSearchContainer);
+                mToolBarFrame.removeView(mSelectionContainer);
+                if (mSelectionMode) {
                     setPortraitTabHeight(0);
-                    mToolBarFrame.removeView(mSelectionContainer);
-                    addSearchContainer();
-                } else if (mSelectionMode) {
-                    setPortraitTabHeight(0);
-                    mToolbar.removeView(mSearchContainer);
                     addSelectionContainer();
+                } else if (mSearchMode) {
+                    setPortraitTabHeight(0);
+                    addSearchContainer();
                 } else {
                     setPortraitTabHeight(mMaxPortraitTabHeight);
-                    mToolbar.removeView(mSearchContainer);
-                    mToolBarFrame.removeView(mSelectionContainer);
                     addLandscapeViewPagerTabs();
                 }
                 updateDisplayOptions(isSearchModeChanging);
@@ -423,6 +424,9 @@
                 animateTabHeightChange(mMaxPortraitTabHeight, 0);
                 updateDisplayOptions(isSearchModeChanging);
             } else {
+                if (mListener != null) {
+                    mListener.onAction(Action.BEGIN_STOPPING_SEARCH_AND_SELECTION_MODE);
+                }
                 mSelectionContainer.setAlpha(1);
                 animateTabHeightChange(0, mMaxPortraitTabHeight);
                 mSelectionContainer.animate().alpha(0).withEndAction(new Runnable() {
@@ -491,15 +495,17 @@
     private void addSearchContainer() {
         mToolbar.removeView(mSearchContainer);
         mToolbar.addView(mSearchContainer);
+        mSearchContainer.setAlpha(1);
     }
 
     private void addSelectionContainer() {
         mToolBarFrame.removeView(mSelectionContainer);
         mToolBarFrame.addView(mSelectionContainer, 0);
+        mSelectionContainer.setAlpha(1);
     }
 
     private void updateDisplayOptions(boolean isSearchModeChanging) {
-        if (mSearchMode) {
+        if (mSearchMode && !mSelectionMode) {
             setFocusOnSearchView();
             // Since we have the {@link SearchView} in a custom action bar, we must manually handle
             // expanding the {@link SearchView} when a search is initiated. Note that a side effect
diff --git a/src/com/android/contacts/activities/PeopleActivity.java b/src/com/android/contacts/activities/PeopleActivity.java
index 64d7843..6a5d348 100644
--- a/src/com/android/contacts/activities/PeopleActivity.java
+++ b/src/com/android/contacts/activities/PeopleActivity.java
@@ -56,6 +56,7 @@
 import com.android.contacts.common.ContactsUtils;
 import com.android.contacts.common.dialog.ClearFrequentsDialog;
 import com.android.contacts.common.util.ImplicitIntentsUtil;
+import com.android.contacts.common.widget.FloatingActionButtonController;
 import com.android.contacts.editor.EditorIntents;
 import com.android.contacts.interactions.ContactDeletionInteraction;
 import com.android.contacts.common.interactions.ImportExportDialogFragment;
@@ -119,6 +120,9 @@
     private ContactsRequest mRequest;
 
     private ActionBarAdapter mActionBarAdapter;
+    private FloatingActionButtonController mFloatingActionButtonController;
+    private View mFloatingActionButtonContainer;
+    private boolean wasLastFabAnimationScaleIn = false;
 
     private ContactTileListFragment.Listener mFavoritesFragmentListener =
             new StrequentContactListFragmentListener();
@@ -366,12 +370,14 @@
         // Add shadow under toolbar
         ViewUtil.addRectangularOutlineProvider(findViewById(R.id.toolbar_parent), getResources());
 
-        // Configure action button
-        final View floatingActionButtonContainer = findViewById(
-                R.id.floating_action_button_container);
-        ViewUtil.setupFloatingActionButton(floatingActionButtonContainer, getResources());
-        final ImageButton floatingActionButton = (ImageButton) findViewById(R.id.floating_action_button);
+        // Configure floating action button
+        mFloatingActionButtonContainer = findViewById(R.id.floating_action_button_container);
+        final ImageButton floatingActionButton
+                = (ImageButton) findViewById(R.id.floating_action_button);
         floatingActionButton.setOnClickListener(this);
+        initializeFabVisibility();
+        mFloatingActionButtonController = new FloatingActionButtonController(this,
+                mFloatingActionButtonContainer, floatingActionButton);
 
         invalidateOptionsMenuIfNeeded();
     }
@@ -494,6 +500,33 @@
         invalidateOptionsMenuIfNeeded();
     }
 
+    private void initializeFabVisibility() {
+        final boolean hideFab = mActionBarAdapter.isSearchMode()
+                || mActionBarAdapter.isSelectionMode();
+        mFloatingActionButtonContainer.setVisibility(hideFab ? View.GONE : View.VISIBLE);
+        wasLastFabAnimationScaleIn = !hideFab;
+    }
+
+    private void showFabWithAnimation(boolean showFab) {
+        if (mFloatingActionButtonContainer == null) {
+            return;
+        }
+        if (showFab) {
+            if (!wasLastFabAnimationScaleIn) {
+                mFloatingActionButtonContainer.setVisibility(View.VISIBLE);
+                mFloatingActionButtonController.scaleIn(0);
+            }
+            wasLastFabAnimationScaleIn = true;
+
+        } else {
+            if (wasLastFabAnimationScaleIn) {
+                mFloatingActionButtonContainer.setVisibility(View.VISIBLE);
+                mFloatingActionButtonController.scaleOut();
+            }
+            wasLastFabAnimationScaleIn = false;
+        }
+    }
+
     @Override
     public void onContactListFilterChanged() {
         if (mAllFragment == null || !mAllFragment.isAdded()) {
@@ -519,11 +552,16 @@
                 configureFragments(false /* from request */);
                 updateFragmentsVisibility();
                 invalidateOptionsMenu();
+                showFabWithAnimation(/* showFabWithAnimation = */ false);
+                break;
+            case ActionBarAdapter.Listener.Action.BEGIN_STOPPING_SEARCH_AND_SELECTION_MODE:
+                showFabWithAnimation(/* showFabWithAnimation = */ true);
                 break;
             case ActionBarAdapter.Listener.Action.STOP_SEARCH_AND_SELECTION_MODE:
                 setQueryTextToFragment("");
                 updateFragmentsVisibility();
                 invalidateOptionsMenu();
+                showFabWithAnimation(/* showFabWithAnimation = */ true);
                 break;
             case ActionBarAdapter.Listener.Action.CHANGE_SEARCH_QUERY:
                 final String queryString = mActionBarAdapter.getQueryString();
@@ -935,10 +973,8 @@
     private final class CheckBoxListListener implements OnCheckBoxListActionListener {
         @Override
         public void onStartDisplayingCheckBoxes() {
-            if (!mActionBarAdapter.isSearchMode()) {
-                mActionBarAdapter.setSelectionMode(true);
-                invalidateOptionsMenu();
-            }
+            mActionBarAdapter.setSelectionMode(true);
+            invalidateOptionsMenu();
         }
 
         @Override