Merge "Keep primary icon in the same position regardless of text." into oc-mr1-jetpack-dev
diff --git a/car/res/layout/car_paged_list_item_content.xml b/car/res/layout/car_paged_list_item_content.xml
index fd6a8a4..d9c865d 100644
--- a/car/res/layout/car_paged_list_item_content.xml
+++ b/car/res/layout/car_paged_list_item_content.xml
@@ -24,8 +24,7 @@
     <ImageView
         android:id="@+id/primary_icon"
         android:layout_width="@dimen/car_single_line_list_item_height"
-        android:layout_height="@dimen/car_single_line_list_item_height"
-        android:layout_centerVertical="true"/>
+        android:layout_height="@dimen/car_single_line_list_item_height"/>
 
     <!-- Text. -->
     <TextView
diff --git a/car/src/main/java/androidx/car/widget/ListItem.java b/car/src/main/java/androidx/car/widget/ListItem.java
index d292d6b..a04a413 100644
--- a/car/src/main/java/androidx/car/widget/ListItem.java
+++ b/car/src/main/java/androidx/car/widget/ListItem.java
@@ -282,12 +282,15 @@
                                 R.dimen.car_keyline_1));
 
                         if (!TextUtils.isEmpty(mBody)) {
-                            // Set top margin.
+                            // Set icon top margin so that the icon remains in the same position it
+                            // would've been in for non-long-text item, namely so that the center
+                            // line of icon matches that of line item.
                             layoutParams.removeRule(RelativeLayout.CENTER_VERTICAL);
-                            layoutParams.topMargin = mContext.getResources().getDimensionPixelSize(
-                                    R.dimen.car_padding_4);
+                            int itemHeight = mContext.getResources().getDimensionPixelSize(
+                                    R.dimen.car_double_line_list_item_height);
+                            layoutParams.topMargin = (itemHeight - iconSize) / 2;
                         } else {
-                            // Centered vertically.
+                            // If the icon can be centered vertically, leave the work for framework.
                             layoutParams.addRule(RelativeLayout.CENTER_VERTICAL);
                             layoutParams.topMargin = 0;
                         }
diff --git a/car/tests/src/androidx/car/widget/ListItemTest.java b/car/tests/src/androidx/car/widget/ListItemTest.java
index 8d2096a..1cbbc9d 100644
--- a/car/tests/src/androidx/car/widget/ListItemTest.java
+++ b/car/tests/src/androidx/car/widget/ListItemTest.java
@@ -366,6 +366,49 @@
     }
 
     @Test
+    public void testSmallPrimaryIconTopMarginRemainsTheSameRegardlessOfTextLength() {
+        final String longText = InstrumentationRegistry.getContext().getResources().getString(
+                R.string.over_120_chars);
+        List<ListItem> items = Arrays.asList(
+                // Single line item.
+                new ListItem.Builder(mActivity)
+                        .withPrimaryActionIcon(android.R.drawable.sym_def_app_icon, false)
+                        .withTitle("one line text")
+                        .build(),
+                // Double line item with one line text.
+                new ListItem.Builder(mActivity)
+                        .withPrimaryActionIcon(android.R.drawable.sym_def_app_icon, false)
+                        .withTitle("one line text")
+                        .withBody("one line text")
+                        .build(),
+                // Double line item with long text.
+                new ListItem.Builder(mActivity)
+                        .withPrimaryActionIcon(android.R.drawable.sym_def_app_icon, false)
+                        .withTitle("one line text")
+                        .withBody(longText)
+                        .build(),
+                // Body text only - long text.
+                new ListItem.Builder(mActivity)
+                        .withPrimaryActionIcon(android.R.drawable.sym_def_app_icon, false)
+                        .withBody(longText)
+                        .build(),
+                // Body text only - one line text.
+                new ListItem.Builder(mActivity)
+                        .withPrimaryActionIcon(android.R.drawable.sym_def_app_icon, false)
+                        .withBody("one line text")
+                        .build());
+        setupPagedListView(items);
+
+        for (int i = 1; i < items.size(); i++) {
+            onView(withId(R.id.recycler_view)).perform(scrollToPosition(i));
+            // Implementation uses integer division so it may be off by 1 vs centered vertically.
+            assertThat((double) getViewHolderAtPosition(i - 1).getPrimaryIcon().getTop(),
+                    is(closeTo(
+                    (double) getViewHolderAtPosition(i).getPrimaryIcon().getTop(), 1.0d)));
+        }
+    }
+
+    @Test
     public void testClickingPrimaryActionIsSeparateFromSupplementalAction() {
         final boolean[] clicked = {false, false};
         List<ListItem> items = Arrays.asList(