Merge "Mitigate some of the jank in opening/closeing search."
diff --git a/java/com/android/dialer/main/impl/MainSearchController.java b/java/com/android/dialer/main/impl/MainSearchController.java
index 46f6a90..c2ff051 100644
--- a/java/com/android/dialer/main/impl/MainSearchController.java
+++ b/java/com/android/dialer/main/impl/MainSearchController.java
@@ -84,6 +84,9 @@
   private final MainToolbar toolbar;
   private final View toolbarShadow;
 
+  /** View located underneath the toolbar that needs to animate with it. */
+  private final View fragmentContainer;
+
   private final List<OnSearchShowListener> onSearchShowListenerList = new ArrayList<>();
 
   /**
@@ -91,7 +94,6 @@
    * want to wait until onPause is called otherwise the transition will look extremely janky.
    */
   private boolean closeSearchOnPause;
-
   private boolean requestingPermission;
 
   public MainSearchController(
@@ -99,12 +101,14 @@
       BottomNavBar bottomNav,
       FloatingActionButton fab,
       MainToolbar toolbar,
-      View toolbarShadow) {
+      View toolbarShadow,
+      View fragmentContainer) {
     this.activity = activity;
     this.bottomNav = bottomNav;
     this.fab = fab;
     this.toolbar = toolbar;
     this.toolbarShadow = toolbarShadow;
+    this.fragmentContainer = fragmentContainer;
   }
 
   /** Should be called if we're showing the dialpad because of a new ACTION_DIAL intent. */
@@ -134,9 +138,10 @@
     Logger.get(activity).logScreenView(ScreenEvent.Type.MAIN_DIALPAD, activity);
 
     fab.hide();
-    toolbar.slideUp(animate);
+    toolbar.slideUp(animate, fragmentContainer);
     toolbar.expand(animate, Optional.absent());
     toolbarShadow.setVisibility(View.VISIBLE);
+
     activity.setTitle(R.string.dialpad_activity_title);
 
     FragmentTransaction transaction = activity.getFragmentManager().beginTransaction();
@@ -147,19 +152,13 @@
       // TODO(a bug): zero suggest results aren't actually shown but this enabled the nearby
       // places promo to be shown.
       searchFragment = NewSearchFragment.newInstance(/* showZeroSuggest=*/ true);
-      transaction.replace(R.id.fragment_container, searchFragment, SEARCH_FRAGMENT_TAG);
-      transaction.addToBackStack(null);
+      transaction.add(R.id.search_fragment_container, searchFragment, SEARCH_FRAGMENT_TAG);
       transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
     } else if (!isSearchVisible()) {
       transaction.show(searchFragment);
     }
     searchFragment.setQuery("", CallInitiationType.Type.DIALPAD);
 
-    // Split the transactions so that the dialpad fragment isn't popped off the stack when we exit
-    // search. We do this so that the dialpad actually animates down instead of just disappearing.
-    transaction.commit();
-    transaction = activity.getFragmentManager().beginTransaction();
-
     // Show Dialpad
     if (getDialpadFragment() == null) {
       DialpadFragment dialpadFragment = new DialpadFragment();
@@ -184,12 +183,12 @@
    *
    * @see {@link #closeSearch(boolean)} to "remove" the dialpad.
    */
-  private void hideDialpad(boolean animate, boolean bottomNavVisible) {
+  private void hideDialpad(boolean animate) {
     LogUtil.enterBlock("MainSearchController.hideDialpad");
     Assert.checkArgument(isDialpadVisible());
 
     fab.show();
-    toolbar.slideDown(animate);
+    toolbar.slideDown(animate, fragmentContainer);
     toolbar.transferQueryFromDialpad(getDialpadFragment().getQuery());
     activity.setTitle(R.string.main_activity_label);
 
@@ -199,15 +198,7 @@
         animate,
         new AnimationListener() {
           @Override
-          public void onAnimationStart(Animation animation) {
-            // Slide the bottom nav on animation start so it's (not) visible when the dialpad
-            // finishes animating down.
-            if (bottomNavVisible) {
-              showBottomNav();
-            } else {
-              hideBottomNav();
-            }
-          }
+          public void onAnimationStart(Animation animation) {}
 
           @Override
           public void onAnimationEnd(Animation animation) {
@@ -257,7 +248,7 @@
       } else {
         Logger.get(activity)
             .logImpression(DialerImpression.Type.MAIN_TOUCH_DIALPAD_SEARCH_LIST_TO_HIDE_DIALPAD);
-        hideDialpad(/* animate=*/ true, /* bottomNavVisible=*/ false);
+        hideDialpad(/* animate=*/ true);
       }
     } else if (isSearchVisible()) {
       if (TextUtils.isEmpty(toolbar.getQuery())) {
@@ -282,7 +273,7 @@
       LogUtil.i("MainSearchController.onBackPressed", "Dialpad visible with query");
       Logger.get(activity)
           .logImpression(DialerImpression.Type.MAIN_PRESS_BACK_BUTTON_TO_HIDE_DIALPAD);
-      hideDialpad(/* animate=*/ true, /* bottomNavVisible=*/ false);
+      hideDialpad(/* animate=*/ true);
       return true;
     } else if (isSearchVisible()) {
       LogUtil.i("MainSearchController.onBackPressed", "Search is visible");
@@ -298,22 +289,19 @@
     }
   }
 
-  /**
-   * Calls {@link #hideDialpad(boolean, boolean)}, removes the search fragment and clears the
-   * dialpad.
-   */
+  /** Calls {@link #hideDialpad(boolean)}, removes the search fragment and clears the dialpad. */
   private void closeSearch(boolean animate) {
     LogUtil.enterBlock("MainSearchController.closeSearch");
     Assert.checkArgument(isSearchVisible());
     if (isDialpadVisible()) {
-      hideDialpad(animate, /* bottomNavVisible=*/ true);
+      hideDialpad(animate);
     } else if (!fab.isShown()) {
       fab.show();
     }
     showBottomNav();
     toolbar.collapse(animate);
     toolbarShadow.setVisibility(View.GONE);
-    activity.getFragmentManager().popBackStack();
+    activity.getFragmentManager().beginTransaction().hide(getSearchFragment()).commit();
 
     // Clear the dialpad so the phone number isn't persisted between search sessions.
     DialpadFragment dialpadFragment = getDialpadFragment();
@@ -391,8 +379,7 @@
       // TODO(a bug): zero suggest results aren't actually shown but this enabled the nearby
       // places promo to be shown.
       searchFragment = NewSearchFragment.newInstance(true);
-      transaction.replace(R.id.fragment_container, searchFragment, SEARCH_FRAGMENT_TAG);
-      transaction.addToBackStack(null);
+      transaction.add(R.id.search_fragment_container, searchFragment, SEARCH_FRAGMENT_TAG);
       transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
     } else if (!isSearchVisible()) {
       transaction.show(getSearchFragment());
@@ -519,7 +506,7 @@
       toolbar.expand(false, Optional.absent());
     }
     if (savedInstanceState.getBoolean(KEY_IS_TOOLBAR_SLIDE_UP, false)) {
-      toolbar.slideUp(false);
+      toolbar.slideUp(false, fragmentContainer);
     }
   }
 
diff --git a/java/com/android/dialer/main/impl/OldMainActivityPeer.java b/java/com/android/dialer/main/impl/OldMainActivityPeer.java
index 9f15d28..2db331a 100644
--- a/java/com/android/dialer/main/impl/OldMainActivityPeer.java
+++ b/java/com/android/dialer/main/impl/OldMainActivityPeer.java
@@ -230,7 +230,7 @@
 
     searchController =
         getNewMainSearchController(
-            bottomNav, fab, toolbar, activity.findViewById(R.id.toolbar_shadow));
+            bottomNav, fab, toolbar, activity.findViewById(R.id.toolbar_shadow), snackbarContainer);
     toolbar.setSearchBarListener(searchController);
 
     onDialpadQueryChangedListener = getNewOnDialpadQueryChangedListener(searchController);
@@ -579,8 +579,10 @@
       BottomNavBar bottomNavBar,
       FloatingActionButton fab,
       MainToolbar mainToolbar,
-      View toolbarShadow) {
-    return new MainSearchController(activity, bottomNavBar, fab, mainToolbar, toolbarShadow);
+      View toolbarShadow,
+      View fragmentContainer) {
+    return new MainSearchController(
+        activity, bottomNavBar, fab, mainToolbar, toolbarShadow, fragmentContainer);
   }
 
   public MainOnDialpadQueryChangedListener getNewOnDialpadQueryChangedListener(
diff --git a/java/com/android/dialer/main/impl/res/layout/main_activity.xml b/java/com/android/dialer/main/impl/res/layout/main_activity.xml
index 0883ace..a1d6e53 100644
--- a/java/com/android/dialer/main/impl/res/layout/main_activity.xml
+++ b/java/com/android/dialer/main/impl/res/layout/main_activity.xml
@@ -21,6 +21,11 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent">
 
+  <!-- MainToolbar -->
+  <include
+      android:id="@+id/toolbar"
+      layout="@layout/toolbar_layout"/>
+
   <android.support.design.widget.CoordinatorLayout
       xmlns:android="http://schemas.android.com/apk/res/android"
       xmlns:app="http://schemas.android.com/apk/res-auto"
@@ -34,8 +39,20 @@
     <FrameLayout
         android:id="@+id/fragment_container"
         android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:layout_above="@+id/bottom_nav_bar"/>
+        android:layout_height="match_parent"/>
+
+    <FrameLayout
+        android:id="@+id/search_fragment_container"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"/>
+
+    <ImageView
+        android:id="@+id/toolbar_shadow"
+        android:layout_width="match_parent"
+        android:layout_height="2dp"
+        android:scaleType="fitXY"
+        android:src="@drawable/search_shadow"
+        android:visibility="gone"/>
 
     <com.android.dialer.widget.DialerFloatingActionButton
         android:id="@+id/fab"
@@ -63,20 +80,6 @@
       android:layout_height="match_parent"
       android:elevation="10dp"/>
 
-  <!-- MainToolbar -->
-  <include
-      android:id="@+id/toolbar"
-      layout="@layout/toolbar_layout"/>
-
-  <ImageView
-      android:id="@+id/toolbar_shadow"
-      android:layout_width="match_parent"
-      android:layout_height="2dp"
-      android:scaleType="fitXY"
-      android:src="@drawable/search_shadow"
-      android:layout_below="@+id/toolbar"
-      android:visibility="gone"/>
-
   <!-- TODO(calderwoodra): investigate what this is for and why we want it. -->
   <!-- Host container for the contact tile drag shadow -->
   <FrameLayout
diff --git a/java/com/android/dialer/main/impl/toolbar/MainToolbar.java b/java/com/android/dialer/main/impl/toolbar/MainToolbar.java
index 2f36717..68876dd 100644
--- a/java/com/android/dialer/main/impl/toolbar/MainToolbar.java
+++ b/java/com/android/dialer/main/impl/toolbar/MainToolbar.java
@@ -16,8 +16,6 @@
 
 package com.android.dialer.main.impl.toolbar;
 
-import android.animation.ValueAnimator;
-import android.animation.ValueAnimator.AnimatorUpdateListener;
 import android.content.Context;
 import android.support.annotation.NonNull;
 import android.support.annotation.StringRes;
@@ -25,10 +23,10 @@
 import android.support.v7.widget.Toolbar;
 import android.util.AttributeSet;
 import android.view.MenuItem;
+import android.view.View;
 import android.view.animation.AccelerateDecelerateInterpolator;
 import android.widget.ImageButton;
 import android.widget.PopupMenu;
-import android.widget.RelativeLayout;
 import com.android.dialer.common.Assert;
 import com.android.dialer.util.ViewUtil;
 import com.google.common.base.Optional;
@@ -73,47 +71,41 @@
   }
 
   /** Slides the toolbar up and off the screen. */
-  public void slideUp(boolean animate) {
+  public void slideUp(boolean animate, View container) {
     Assert.checkArgument(!isSlideUp);
     if (getHeight() == 0) {
-      ViewUtil.doOnGlobalLayout(this, view -> slideUp(animate));
+      ViewUtil.doOnGlobalLayout(this, view -> slideUp(animate, container));
       return;
     }
     isSlideUp = true;
-    ValueAnimator animator = ValueAnimator.ofFloat(0, -getHeight());
-    animator.setDuration(animate ? SLIDE_DURATION : 0);
-    animator.setInterpolator(SLIDE_INTERPOLATOR);
-    animator.addUpdateListener(
-        new AnimatorUpdateListener() {
-          @Override
-          public void onAnimationUpdate(ValueAnimator animation) {
-            int val = ((Float) animation.getAnimatedValue()).intValue();
-            RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) getLayoutParams();
-            params.topMargin = val;
-            requestLayout();
-          }
-        });
-    animator.start();
+    animate()
+        .translationY(-getHeight())
+        .setDuration(animate ? SLIDE_DURATION : 0)
+        .setInterpolator(SLIDE_INTERPOLATOR)
+        .start();
+    container
+        .animate()
+        .translationY(-getHeight())
+        .setDuration(animate ? SLIDE_DURATION : 0)
+        .setInterpolator(SLIDE_INTERPOLATOR)
+        .start();
   }
 
   /** Slides the toolbar down and back onto the screen. */
-  public void slideDown(boolean animate) {
+  public void slideDown(boolean animate, View container) {
     Assert.checkArgument(isSlideUp);
     isSlideUp = false;
-    ValueAnimator animator = ValueAnimator.ofFloat(-getHeight(), 0);
-    animator.setDuration(animate ? SLIDE_DURATION : 0);
-    animator.setInterpolator(SLIDE_INTERPOLATOR);
-    animator.addUpdateListener(
-        new AnimatorUpdateListener() {
-          @Override
-          public void onAnimationUpdate(ValueAnimator animation) {
-            int val = ((Float) animation.getAnimatedValue()).intValue();
-            RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) getLayoutParams();
-            params.topMargin = val;
-            requestLayout();
-          }
-        });
-    animator.start();
+    animate()
+        .translationY(0)
+        .setDuration(animate ? SLIDE_DURATION : 0)
+        .setInterpolator(SLIDE_INTERPOLATOR)
+        .start();
+    container
+        .animate()
+        .translationY(0)
+        .setDuration(animate ? SLIDE_DURATION : 0)
+        .setInterpolator(SLIDE_INTERPOLATOR)
+        .start();
   }
 
   /** @see SearchBarView#collapse(boolean) */
diff --git a/java/com/android/dialer/main/impl/toolbar/SearchBarView.java b/java/com/android/dialer/main/impl/toolbar/SearchBarView.java
index 2999850..0cc7659 100644
--- a/java/com/android/dialer/main/impl/toolbar/SearchBarView.java
+++ b/java/com/android/dialer/main/impl/toolbar/SearchBarView.java
@@ -186,7 +186,6 @@
     params.rightMargin = margin;
     searchBoxExpanded.getLayoutParams().height =
         (int) (animationEndHeight - (animationEndHeight - animationStartHeight) * fraction);
-    requestLayout();
   }
 
   /* package-private */ void setSearchBarListener(@NonNull SearchBarListener listener) {