Fix jank in no favorites screen when showing/hiding dialpad DO NOT MERGE

Reintroduce a spacer view (under the no favorites view) that is
the same height as the search box + its margins, so that
the no favorites view does not shift when the dialpad is shown/hidden

Bug: 13341743
Change-Id: I00171b5fd546e30394c95d31976483d124f75f3b
(cherry picked from commit b0d197653fcdd2526ba9b85d613e4968ebbef2ab)
diff --git a/res/layout/dialtacts_activity.xml b/res/layout/dialtacts_activity.xml
index 8f9f39c..6eea633 100644
--- a/res/layout/dialtacts_activity.xml
+++ b/res/layout/dialtacts_activity.xml
@@ -140,6 +140,12 @@
                     android:layout_alignParentRight="true"
                     />
             </RelativeLayout>
+            <Space
+                android:id="@+id/contact_tile_frame_spacer"
+                android:layout_height="wrap_content"
+                android:layout_width="match_parent"
+                android:layout_alignParentBottom="true"
+                android:visibility="gone"/>
         </LinearLayout>
     </FrameLayout>
 
diff --git a/res/layout/phone_favorites_fragment.xml b/res/layout/phone_favorites_fragment.xml
index 23987a8..d1ff3d7 100644
--- a/res/layout/phone_favorites_fragment.xml
+++ b/res/layout/phone_favorites_fragment.xml
@@ -58,5 +58,4 @@
         android:layout_alignParentBottom="true"
         layout="@layout/phone_no_favorites"
         android:visibility="gone"/>
-
 </RelativeLayout>
diff --git a/res/layout/phone_no_favorites.xml b/res/layout/phone_no_favorites.xml
index 1a0079f..b95afd1 100644
--- a/res/layout/phone_no_favorites.xml
+++ b/res/layout/phone_no_favorites.xml
@@ -18,7 +18,6 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:orientation="vertical"
     android:minHeight="?android:attr/listPreferredItemHeight">
 
     <include
@@ -33,23 +32,18 @@
     <LinearLayout
         android:id="@+id/nofavorite_frame"
         android:layout_width="match_parent"
-        android:layout_height="match_parent"
+        android:layout_height="wrap_content"
         android:orientation="vertical"
-        android:layout_gravity="center"
         android:gravity="center"
-        android:layout_alignParentLeft="true"
-        android:layout_alignParentStart="true"
-        android:layout_alignParentTop="true"
-        android:layout_above="@id/show_all_contact_button_in_nofav">
-
+        android:layout_centerInParent="true">
         <ImageView
             android:id="@+id/nofavorite_image"
             android:layout_height="wrap_content"
             android:layout_width="match_parent"
             android:gravity="center_horizontal"
             android:src="@drawable/no_favorites_banner"
-            android:layout_marginBottom="14dp"/>
-
+            android:layout_marginBottom="14dp"
+            android:contentDescription="@string/no_favorites"/>
         <TextView
             android:id="@+id/title"
             android:layout_width="match_parent"
diff --git a/src/com/android/dialer/DialtactsActivity.java b/src/com/android/dialer/DialtactsActivity.java
index c510355..eee3838 100644
--- a/src/com/android/dialer/DialtactsActivity.java
+++ b/src/com/android/dialer/DialtactsActivity.java
@@ -45,9 +45,12 @@
 import android.view.Menu;
 import android.view.MenuItem;
 import android.view.View;
+import android.view.ViewGroup.LayoutParams;
+import android.view.ViewTreeObserver.OnGlobalLayoutListener;
 import android.view.inputmethod.InputMethodManager;
 import android.widget.AbsListView.OnScrollListener;
 import android.widget.EditText;
+import android.widget.LinearLayout;
 import android.widget.PopupMenu;
 import android.widget.Toast;
 
@@ -150,7 +153,9 @@
     private View mDialButton;
     private PopupMenu mOverflowMenu;
 
-    // Padding view used to shift the fragments up when the dialpad is shown.
+    // Padding view used to shift the fragment frame up when the dialpad is shown so that
+    // the contents of the fragment frame continue to exist in a layout of the same height
+    private View mFragmentsSpacer;
     private View mFragmentsFrame;
 
     private boolean mInDialpadSearch;
@@ -311,9 +316,26 @@
         }
 
         mFragmentsFrame = findViewById(R.id.dialtacts_frame);
+        mFragmentsSpacer = findViewById(R.id.contact_tile_frame_spacer);
 
         mRemoveViewContainer = (RemoveView) findViewById(R.id.remove_view_container);
-        mSearchAndRemoveViewContainer = (View) findViewById(R.id.search_and_remove_view_container);
+        mSearchAndRemoveViewContainer = findViewById(R.id.search_and_remove_view_container);
+
+        // When the first global layout pass is completed (and mSearchAndRemoveViewContainer has
+        // been assigned a valid height), assign that height to mFragmentsSpacer as well.
+        mSearchAndRemoveViewContainer.getViewTreeObserver().addOnGlobalLayoutListener(
+                new OnGlobalLayoutListener() {
+                    @Override
+                    public void onGlobalLayout() {
+                        mSearchAndRemoveViewContainer.getViewTreeObserver()
+                                .removeOnGlobalLayoutListener(this);
+                        mFragmentsSpacer.setLayoutParams(
+                                new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT,
+                                        mSearchAndRemoveViewContainer.getHeight()));
+                    }
+                });
+
+
         prepareSearchView();
 
         if (UI.FILTER_CONTACTS_ACTION.equals(intent.getAction())
@@ -588,6 +610,7 @@
 
     public void hideSearchBar() {
         final int height = mSearchAndRemoveViewContainer.getHeight();
+
         mSearchAndRemoveViewContainer.animate().cancel();
         mSearchAndRemoveViewContainer.setAlpha(1);
         mSearchAndRemoveViewContainer.setTranslationY(0);
@@ -601,6 +624,10 @@
                     @Override
                     public void onAnimationEnd(Animator animation) {
                         mFragmentsFrame.setTranslationY(0);
+                        // Display the fragments spacer (which has the same height as the
+                        // search box) now that the search box is hidden, so that
+                        // mFragmentsFrame always retains the same height
+                        mFragmentsSpacer.setVisibility(View.VISIBLE);
                     }
                 });
     }
@@ -624,6 +651,9 @@
                         new AnimatorListenerAdapter() {
                             @Override
                             public void onAnimationStart(Animator animation) {
+                                // Hide the fragment spacer now that the search box will
+                                // be displayed again
+                                mFragmentsSpacer.setVisibility(View.GONE);
                             }
                         });
     }