Make dialpad key alignment responsive to font size.

In portrait mode, we surround the icon and letters with a linear layout so that we can adjust its height.
In landscape mode, we add a horizontal placeholder to each key's layout so that we can adjust its width.

This approach was put forward by Ryan Oldenburg (roldenburg@).

Bug: 30215380
Test: Manual
PiperOrigin-RevId: 173717443
Change-Id: I9b60657ca20d371a60c303a9683578663fc28a09
diff --git a/java/com/android/dialer/dialpadview/DialpadView.java b/java/com/android/dialer/dialpadview/DialpadView.java
index 0c53273..d70b0a6 100644
--- a/java/com/android/dialer/dialpadview/DialpadView.java
+++ b/java/com/android/dialer/dialpadview/DialpadView.java
@@ -39,6 +39,7 @@
 import android.widget.LinearLayout;
 import android.widget.TextView;
 import com.android.dialer.animation.AnimUtils;
+import com.android.dialer.common.Assert;
 import com.android.dialer.common.LogUtil;
 import com.android.dialer.compat.CompatUtils;
 import java.text.DecimalFormat;
@@ -50,16 +51,13 @@
 
   private static final String TAG = DialpadView.class.getSimpleName();
 
+  // Parameters for animation
   private static final double DELAY_MULTIPLIER = 0.66;
   private static final double DURATION_MULTIPLIER = 0.8;
-  // For animation.
   private static final int KEY_FRAME_DURATION = 33;
-  /** {@code True} if the dialpad is in landscape orientation. */
-  private final boolean mIsLandscape;
-  /** {@code True} if the dialpad is showing in a right-to-left locale. */
-  private final boolean mIsRtl;
 
-  private final int[] mButtonIds =
+  // Resource IDs for buttons (0-9, *, and #)
+  private static final int[] BUTTON_IDS =
       new int[] {
         R.id.zero,
         R.id.one,
@@ -74,6 +72,30 @@
         R.id.star,
         R.id.pound
       };
+
+  // Resource IDs for the button-letter mapping
+  private static final int[] LETTER_MAPPING_IDS =
+      new int[] {
+        R.string.dialpad_0_letters,
+        R.string.dialpad_1_letters,
+        R.string.dialpad_2_letters,
+        R.string.dialpad_3_letters,
+        R.string.dialpad_4_letters,
+        R.string.dialpad_5_letters,
+        R.string.dialpad_6_letters,
+        R.string.dialpad_7_letters,
+        R.string.dialpad_8_letters,
+        R.string.dialpad_9_letters,
+        R.string.dialpad_star_letters,
+        R.string.dialpad_pound_letters
+      };
+
+  // Whether the device is in landscape mode
+  private final boolean mIsLandscape;
+
+  // Whether the dialpad is shown in a right-to-left locale
+  private final boolean mIsRtl;
+
   private EditText mDigits;
   private ImageButton mDelete;
   private View mOverflowMenuButton;
@@ -110,6 +132,8 @@
 
   @Override
   protected void onFinishInflate() {
+    super.onFinishInflate();
+
     setupKeypad();
     mDigits = (EditText) findViewById(R.id.digits);
     mDelete = (ImageButton) findViewById(R.id.deleteButton);
@@ -127,28 +151,8 @@
   }
 
   private void setupKeypad() {
-    final int[] letterIds =
-        new int[] {
-          R.string.dialpad_0_letters,
-          R.string.dialpad_1_letters,
-          R.string.dialpad_2_letters,
-          R.string.dialpad_3_letters,
-          R.string.dialpad_4_letters,
-          R.string.dialpad_5_letters,
-          R.string.dialpad_6_letters,
-          R.string.dialpad_7_letters,
-          R.string.dialpad_8_letters,
-          R.string.dialpad_9_letters,
-          R.string.dialpad_star_letters,
-          R.string.dialpad_pound_letters
-        };
-
     final Resources resources = getContext().getResources();
 
-    DialpadKeyButton dialpadKey;
-    TextView numberView;
-    TextView lettersView;
-
     final Locale currentLocale = resources.getConfiguration().locale;
     final NumberFormat nf;
     // We translate dialpad numbers only for "fa" and not any other locale
@@ -159,17 +163,16 @@
       nf = DecimalFormat.getInstance(Locale.ENGLISH);
     }
 
-    for (int i = 0; i < mButtonIds.length; i++) {
-      dialpadKey = (DialpadKeyButton) findViewById(mButtonIds[i]);
-      numberView = (TextView) dialpadKey.findViewById(R.id.dialpad_key_number);
-      lettersView = (TextView) dialpadKey.findViewById(R.id.dialpad_key_letters);
+    for (int i = 0; i < BUTTON_IDS.length; i++) {
+      DialpadKeyButton dialpadKey = (DialpadKeyButton) findViewById(BUTTON_IDS[i]);
+      TextView numberView = (TextView) dialpadKey.findViewById(R.id.dialpad_key_number);
 
       final String numberString;
       final CharSequence numberContentDescription;
-      if (mButtonIds[i] == R.id.pound) {
+      if (BUTTON_IDS[i] == R.id.pound) {
         numberString = resources.getString(R.string.dialpad_pound_number);
         numberContentDescription = numberString;
-      } else if (mButtonIds[i] == R.id.star) {
+      } else if (BUTTON_IDS[i] == R.id.star) {
         numberString = resources.getString(R.string.dialpad_star_number);
         numberContentDescription = numberString;
       } else {
@@ -177,7 +180,7 @@
         // The content description is used for Talkback key presses. The number is
         // separated by a "," to introduce a slight delay. Convert letters into a verbatim
         // span so that they are read as letters instead of as one word.
-        String letters = resources.getString(letterIds[i]);
+        String letters = resources.getString(LETTER_MAPPING_IDS[i]);
         Spannable spannable =
             Spannable.Factory.getInstance().newSpannable(numberString + "," + letters);
         spannable.setSpan(
@@ -199,8 +202,9 @@
       dialpadKey.setContentDescription(numberContentDescription);
       dialpadKey.setBackground(rippleBackground);
 
+      TextView lettersView = (TextView) dialpadKey.findViewById(R.id.dialpad_key_letters);
       if (lettersView != null) {
-        lettersView.setText(resources.getString(letterIds[i]));
+        lettersView.setText(resources.getString(LETTER_MAPPING_IDS[i]));
       }
     }
 
@@ -211,6 +215,103 @@
     zero.setLongHoverContentDescription(resources.getText(R.string.description_image_button_plus));
   }
 
+  @Override
+  protected void onLayout(boolean changed, int l, int t, int r, int b) {
+    super.onLayout(changed, l, t, r, b);
+
+    if (changed) {
+      if (mIsLandscape) {
+        adjustKeyWidths();
+      } else {
+        adjustKeyHeightsInFirstRow();
+      }
+    }
+  }
+
+  /**
+   * Adjust key heights in the first row.
+   *
+   * <p>A voice mail icon is shown under key "1", which makes its height different from other keys
+   * in the first row.
+   *
+   * <p>This method should be called after the sizes of related layouts have been calculated by the
+   * framework.
+   */
+  private void adjustKeyHeightsInFirstRow() {
+    int maxHeight = 0;
+    for (int i = 1; i <= 3; i++) {
+      DialpadKeyButton dialpadKey = (DialpadKeyButton) findViewById(BUTTON_IDS[i]);
+      LinearLayout keyLayout = (LinearLayout) dialpadKey.findViewById(R.id.dialpad_key_layout);
+      maxHeight = Math.max(maxHeight, keyLayout.getHeight());
+    }
+
+    for (int i = 1; i <= 3; i++) {
+      DialpadKeyButton dialpadKey = (DialpadKeyButton) findViewById(BUTTON_IDS[i]);
+      LinearLayout keyLayout = (LinearLayout) dialpadKey.findViewById(R.id.dialpad_key_layout);
+
+      DialpadTextView numberView =
+          (DialpadTextView) keyLayout.findViewById(R.id.dialpad_key_number);
+      MarginLayoutParams numberViewLayoutParams = (MarginLayoutParams) numberView.getLayoutParams();
+
+      LinearLayout iconOrLettersLayout =
+          (LinearLayout) keyLayout.findViewById(R.id.dialpad_key_icon_or_letters_layout);
+      iconOrLettersLayout.setLayoutParams(
+          new LayoutParams(
+              LayoutParams.WRAP_CONTENT /* width */,
+              maxHeight
+                  - numberView.getHeight()
+                  - numberViewLayoutParams.topMargin
+                  - numberViewLayoutParams.bottomMargin /* height */));
+    }
+  }
+
+  /**
+   * Adjust key widths to align keys in each column.
+   *
+   * <p>When the device is in landscape mode, we first find the maximum among a pre-defined width
+   * and the width of each key layout. Then we adjust the width of each layout's horizontal
+   * placeholder to align keys in each column. This is to accommodate the scenario where not all
+   * letters associated with a key can be displayed in one line due to large font size.
+   *
+   * <p>This method should be called after the sizes of related layouts have been calculated by the
+   * framework.
+   */
+  private void adjustKeyWidths() {
+    Assert.checkState(mIsLandscape);
+
+    // A pre-defined minimum width for the letters shown beside a key.
+    final int minimumKeyLettersWidth =
+        getContext().getResources().getDimensionPixelSize(R.dimen.dialpad_key_text_width);
+
+    // The maximum width of the key layouts. A key layout includes both the number and the letters.
+    int maxWidth = 0;
+
+    for (int buttonId : BUTTON_IDS) {
+      DialpadKeyButton dialpadKey = (DialpadKeyButton) findViewById(buttonId);
+      LinearLayout keyLayout = (LinearLayout) dialpadKey.findViewById(R.id.dialpad_key_layout);
+      TextView keyLettersView = (TextView) keyLayout.findViewById(R.id.dialpad_key_letters);
+      if (keyLettersView != null && keyLettersView.getWidth() < minimumKeyLettersWidth) {
+        // If the width of the letters is less than the pre-defined minimum, use the pre-defined
+        // minimum to obtain the maximum width.
+        maxWidth =
+            Math.max(
+                maxWidth,
+                keyLayout.getWidth() - keyLettersView.getWidth() + minimumKeyLettersWidth);
+      } else {
+        maxWidth = Math.max(maxWidth, keyLayout.getWidth());
+      }
+    }
+
+    for (int buttonId : BUTTON_IDS) {
+      DialpadKeyButton dialpadKey = (DialpadKeyButton) findViewById(buttonId);
+      LinearLayout keyLayout = (LinearLayout) dialpadKey.findViewById(R.id.dialpad_key_layout);
+      View horizontalPlaceholder = keyLayout.findViewById(R.id.dialpad_key_horizontal_placeholder);
+      horizontalPlaceholder.setLayoutParams(
+          new LayoutParams(
+              maxWidth - keyLayout.getWidth() /* width */, LayoutParams.MATCH_PARENT /* height */));
+    }
+  }
+
   private Drawable getDrawableCompat(Context context, int id) {
     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
       return context.getDrawable(id);
@@ -275,10 +376,10 @@
     // numbers appear at their original position (0) momentarily before animating.
     final AnimatorListenerAdapter showListener = new AnimatorListenerAdapter() {};
 
-    for (int i = 0; i < mButtonIds.length; i++) {
-      int delay = (int) (getKeyButtonAnimationDelay(mButtonIds[i]) * DELAY_MULTIPLIER);
-      int duration = (int) (getKeyButtonAnimationDuration(mButtonIds[i]) * DURATION_MULTIPLIER);
-      final DialpadKeyButton dialpadKey = (DialpadKeyButton) findViewById(mButtonIds[i]);
+    for (int i = 0; i < BUTTON_IDS.length; i++) {
+      int delay = (int) (getKeyButtonAnimationDelay(BUTTON_IDS[i]) * DELAY_MULTIPLIER);
+      int duration = (int) (getKeyButtonAnimationDuration(BUTTON_IDS[i]) * DURATION_MULTIPLIER);
+      final DialpadKeyButton dialpadKey = (DialpadKeyButton) findViewById(BUTTON_IDS[i]);
 
       ViewPropertyAnimator animator = dialpadKey.animate();
       if (mIsLandscape) {
diff --git a/java/com/android/dialer/dialpadview/res/layout-land/dialpad_key.xml b/java/com/android/dialer/dialpadview/res/layout-land/dialpad_key.xml
index b126f72..12f24ac 100644
--- a/java/com/android/dialer/dialpadview/res/layout-land/dialpad_key.xml
+++ b/java/com/android/dialer/dialpadview/res/layout-land/dialpad_key.xml
@@ -14,12 +14,13 @@
      limitations under the License.
 -->
 
-<!-- A layout representing a single key in the dialpad -->
+<!-- A layout representing each of keys "2" ~ "9" in the dialpad -->
 <com.android.dialer.dialpadview.DialpadKeyButton
     xmlns:android="http://schemas.android.com/apk/res/android"
     style="@style/DialpadKeyButtonStyle">
 
   <LinearLayout
+      android:id="@+id/dialpad_key_layout"
       style="@style/DialpadKeyInternalLayoutStyle"
       android:layout_gravity="right|center_vertical"
       android:baselineAligned="false"
@@ -34,10 +35,20 @@
           style="@style/DialpadKeyNumberStyle"/>
     </FrameLayout>
 
-    <TextView
-        android:id="@+id/dialpad_key_letters"
-        style="@style/DialpadKeyLettersStyle"
-        android:layout_width="@dimen/dialpad_key_text_width"
-        android:layout_gravity="center"/>
+    <LinearLayout
+        android:id="@+id/dialpad_key_icon_or_letters_layout"
+        style="@style/DialpadKeyInternalLayoutStyle">
+
+      <TextView
+          android:id="@+id/dialpad_key_letters"
+          style="@style/DialpadKeyLettersStyle"/>
+    </LinearLayout>
+
+    <!-- A placeholder to make the width the same as other keys. -->
+    <View
+        android:id="@+id/dialpad_key_horizontal_placeholder"
+        android:layout_width="0dp"
+        android:layout_height="match_parent"/>
   </LinearLayout>
+
 </com.android.dialer.dialpadview.DialpadKeyButton>
diff --git a/java/com/android/dialer/dialpadview/res/layout-land/dialpad_key_one.xml b/java/com/android/dialer/dialpadview/res/layout-land/dialpad_key_one.xml
index 5023413..2f2e725 100644
--- a/java/com/android/dialer/dialpadview/res/layout-land/dialpad_key_one.xml
+++ b/java/com/android/dialer/dialpadview/res/layout-land/dialpad_key_one.xml
@@ -13,12 +13,15 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
+
+<!-- A layout representing key "1" in the dialpad -->
 <com.android.dialer.dialpadview.DialpadKeyButton
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/one"
     style="@style/DialpadKeyButtonStyle">
 
   <LinearLayout
+      android:id="@+id/dialpad_key_layout"
       style="@style/DialpadKeyInternalLayoutStyle"
       android:layout_gravity="right|center_vertical"
       android:baselineAligned="false"
@@ -33,10 +36,10 @@
           style="@style/DialpadKeyNumberStyle"/>
     </FrameLayout>
 
-    <FrameLayout
-        android:layout_width="@dimen/dialpad_key_text_width"
-        android:layout_height="wrap_content"
-        android:layout_gravity="left|center">
+    <LinearLayout
+        android:id="@+id/dialpad_key_icon_or_letters_layout"
+        style="@style/DialpadKeyInternalLayoutStyle">
+
       <ImageView
           android:id="@+id/dialpad_key_voicemail"
           android:layout_width="wrap_content"
@@ -44,6 +47,13 @@
           android:scaleType="fitCenter"
           android:src="@drawable/quantum_ic_voicemail_white_24"
           android:tint="@color/dialpad_voicemail_tint"/>
-    </FrameLayout>
+    </LinearLayout>
+
+    <!-- A placeholder to make the width the same as other dialpad keys. -->
+    <View
+        android:id="@+id/dialpad_key_horizontal_placeholder"
+        android:layout_width="0dp"
+        android:layout_height="match_parent"/>
   </LinearLayout>
+
 </com.android.dialer.dialpadview.DialpadKeyButton>
diff --git a/java/com/android/dialer/dialpadview/res/layout-land/dialpad_key_pound.xml b/java/com/android/dialer/dialpadview/res/layout-land/dialpad_key_pound.xml
index a3e0c7c..613e731 100644
--- a/java/com/android/dialer/dialpadview/res/layout-land/dialpad_key_pound.xml
+++ b/java/com/android/dialer/dialpadview/res/layout-land/dialpad_key_pound.xml
@@ -13,12 +13,15 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
+
+<!-- A layout representing key "#" in the dialpad -->
 <com.android.dialer.dialpadview.DialpadKeyButton
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/pound"
     style="@style/DialpadKeyButtonStyle">
 
   <LinearLayout
+      android:id="@+id/dialpad_key_layout"
       style="@style/DialpadKeyInternalLayoutStyle"
       android:layout_gravity="right|center_vertical"
       android:baselineAligned="false"
@@ -33,8 +36,10 @@
           style="@style/DialpadKeyPoundStyle"/>
     </FrameLayout>
 
+    <!-- A placeholder to make the width the same as other keys. -->
     <View
-        style="@style/DialpadKeyLettersStyle"
-        android:layout_width="@dimen/dialpad_key_text_width"/>
+        android:id="@+id/dialpad_key_horizontal_placeholder"
+        android:layout_width="0dp"
+        android:layout_height="match_parent"/>
   </LinearLayout>
 </com.android.dialer.dialpadview.DialpadKeyButton>
diff --git a/java/com/android/dialer/dialpadview/res/layout-land/dialpad_key_star.xml b/java/com/android/dialer/dialpadview/res/layout-land/dialpad_key_star.xml
index 18dc1cb..2b0a6b5 100644
--- a/java/com/android/dialer/dialpadview/res/layout-land/dialpad_key_star.xml
+++ b/java/com/android/dialer/dialpadview/res/layout-land/dialpad_key_star.xml
@@ -13,12 +13,15 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
+
+<!-- A layout representing key "*" in the dialpad -->
 <com.android.dialer.dialpadview.DialpadKeyButton
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/star"
     style="@style/DialpadKeyButtonStyle">
 
   <LinearLayout
+      android:id="@+id/dialpad_key_layout"
       style="@style/DialpadKeyInternalLayoutStyle"
       android:layout_gravity="right|center_vertical"
       android:baselineAligned="false"
@@ -33,8 +36,10 @@
           style="@style/DialpadKeyStarStyle"/>
     </FrameLayout>
 
+    <!-- A placeholder to make the width the same as other keys. -->
     <View
-        style="@style/DialpadKeyLettersStyle"
-        android:layout_width="@dimen/dialpad_key_text_width"/>
+        android:id="@+id/dialpad_key_horizontal_placeholder"
+        android:layout_width="0dp"
+        android:layout_height="match_parent"/>
   </LinearLayout>
 </com.android.dialer.dialpadview.DialpadKeyButton>
diff --git a/java/com/android/dialer/dialpadview/res/layout-land/dialpad_key_zero.xml b/java/com/android/dialer/dialpadview/res/layout-land/dialpad_key_zero.xml
index 4c46447..7145072 100644
--- a/java/com/android/dialer/dialpadview/res/layout-land/dialpad_key_zero.xml
+++ b/java/com/android/dialer/dialpadview/res/layout-land/dialpad_key_zero.xml
@@ -21,6 +21,7 @@
     style="@style/DialpadKeyButtonStyle">
 
   <LinearLayout
+      android:id="@+id/dialpad_key_layout"
       style="@style/DialpadKeyInternalLayoutStyle"
       android:layout_gravity="right|center_vertical"
       android:baselineAligned="false"
@@ -37,7 +38,11 @@
 
     <TextView
         android:id="@+id/dialpad_key_letters"
-        style="@style/DialpadKeyLettersStyle"
-        android:layout_width="@dimen/dialpad_key_text_width"/>
+        style="@style/DialpadKeyLettersStyle"/>
+    <!-- A placeholder to make the width the same as other keys. -->
+    <View
+        android:id="@+id/dialpad_key_horizontal_placeholder"
+        android:layout_width="0dp"
+        android:layout_height="match_parent"/>
   </LinearLayout>
 </com.android.dialer.dialpadview.DialpadKeyButton>
diff --git a/java/com/android/dialer/dialpadview/res/layout/dialpad_key.xml b/java/com/android/dialer/dialpadview/res/layout/dialpad_key.xml
index 77e4fc5..6c87cd2 100644
--- a/java/com/android/dialer/dialpadview/res/layout/dialpad_key.xml
+++ b/java/com/android/dialer/dialpadview/res/layout/dialpad_key.xml
@@ -14,22 +14,26 @@
      limitations under the License.
 -->
 
-<!-- A layout representing a single key in the dialpad -->
+<!-- A layout representing each of keys "2" ~ "9" in the dialpad -->
 <com.android.dialer.dialpadview.DialpadKeyButton
-  xmlns:android="http://schemas.android.com/apk/res/android"
-  style="@style/DialpadKeyButtonStyle">
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    style="@style/DialpadKeyButtonStyle">
 
-  <LinearLayout style="@style/DialpadKeyInternalLayoutStyle">
-
-    <!-- Note in the referenced styles that we assign hard widths to these components
-         because we want them to line up vertically when we arrange them in an MxN grid -->
+  <LinearLayout
+      android:id="@+id/dialpad_key_layout"
+      style="@style/DialpadKeyInternalLayoutStyle">
 
     <com.android.dialer.dialpadview.DialpadTextView
-      android:id="@+id/dialpad_key_number"
-      style="@style/DialpadKeyNumberStyle"/>
+        android:id="@+id/dialpad_key_number"
+        style="@style/DialpadKeyNumberStyle"/>
 
-    <TextView
-      android:id="@+id/dialpad_key_letters"
-      style="@style/DialpadKeyLettersStyle"/>
+    <LinearLayout
+        android:id="@+id/dialpad_key_icon_or_letters_layout"
+        style="@style/DialpadKeyInternalLayoutStyle">
+
+      <TextView
+          android:id="@+id/dialpad_key_letters"
+          style="@style/DialpadKeyLettersStyle"/>
+    </LinearLayout>
   </LinearLayout>
 </com.android.dialer.dialpadview.DialpadKeyButton>
diff --git a/java/com/android/dialer/dialpadview/res/layout/dialpad_key_one.xml b/java/com/android/dialer/dialpadview/res/layout/dialpad_key_one.xml
index 4401c5b..599c2d8 100644
--- a/java/com/android/dialer/dialpadview/res/layout/dialpad_key_one.xml
+++ b/java/com/android/dialer/dialpadview/res/layout/dialpad_key_one.xml
@@ -13,29 +13,40 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
+
+<!-- A layout representing key "1" in the dialpad -->
 <com.android.dialer.dialpadview.DialpadKeyButton
-  xmlns:android="http://schemas.android.com/apk/res/android"
-  android:id="@+id/one"
-  style="@style/DialpadKeyButtonStyle">
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/one"
+    style="@style/DialpadKeyButtonStyle">
+
   <LinearLayout
-      android:layout_marginTop="1dp"
+      android:id="@+id/dialpad_key_layout"
       style="@style/DialpadKeyInternalLayoutStyle">
+
     <com.android.dialer.dialpadview.DialpadTextView
-      android:id="@+id/dialpad_key_number"
-      style="@style/DialpadKeyNumberStyle"/>
-    <RelativeLayout
-      android:layout_width="wrap_content"
-      android:layout_height="wrap_content">
+        android:id="@+id/dialpad_key_number"
+        style="@style/DialpadKeyNumberStyle"/>
+
+    <LinearLayout
+        android:id="@+id/dialpad_key_icon_or_letters_layout"
+        style="@style/DialpadKeyInternalLayoutStyle">
+
+      <!--
+          A placeholder to make the horizontal center line of the voice mail icon lined up with
+          those of the other buttons in the same row
+      -->
+      <View
+          android:layout_width="match_parent"
+          android:layout_height="1dp"/>
+
       <ImageView
-        android:id="@+id/dialpad_key_voicemail"
-        android:layout_width="wrap_content"
-        android:layout_height="@dimen/dialpad_voicemail_icon_size"
-        android:layout_centerInParent="true"
-        android:scaleType="fitCenter"
-        android:src="@drawable/quantum_ic_voicemail_white_24"
-        android:tint="?attr/dialpad_voicemail_tint"/>
-      <!-- Place empty text view so vertical height is same as other dialpad keys. -->
-      <TextView style="@style/DialpadKeyLettersStyle"/>
-    </RelativeLayout>
+          android:id="@+id/dialpad_key_voicemail"
+          android:layout_width="wrap_content"
+          android:layout_height="@dimen/dialpad_voicemail_icon_size"
+          android:scaleType="fitCenter"
+          android:src="@drawable/quantum_ic_voicemail_white_24"
+          android:tint="?attr/dialpad_voicemail_tint"/>
+    </LinearLayout>
   </LinearLayout>
 </com.android.dialer.dialpadview.DialpadKeyButton>
diff --git a/java/com/android/dialer/dialpadview/res/layout/dialpad_key_pound.xml b/java/com/android/dialer/dialpadview/res/layout/dialpad_key_pound.xml
index d37a6aa..5e47ac0 100644
--- a/java/com/android/dialer/dialpadview/res/layout/dialpad_key_pound.xml
+++ b/java/com/android/dialer/dialpadview/res/layout/dialpad_key_pound.xml
@@ -13,14 +13,19 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
+
+<!-- A layout representing key "#" in the dialpad -->
 <com.android.dialer.dialpadview.DialpadKeyButton
-  xmlns:android="http://schemas.android.com/apk/res/android"
-  android:id="@+id/pound"
-  style="@style/DialpadKeyButtonStyle">
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/pound"
+    style="@style/DialpadKeyButtonStyle">
+
   <LinearLayout
-    style="@style/DialpadKeyInternalLayoutStyle">
+      android:id="@+id/dialpad_key_layout"
+      style="@style/DialpadKeyInternalLayoutStyle">
+
     <com.android.dialer.dialpadview.DialpadTextView
-      android:id="@id/dialpad_key_number"
-      style="@style/DialpadKeyPoundStyle"/>
+        android:id="@id/dialpad_key_number"
+        style="@style/DialpadKeyPoundStyle"/>
   </LinearLayout>
 </com.android.dialer.dialpadview.DialpadKeyButton>
diff --git a/java/com/android/dialer/dialpadview/res/layout/dialpad_key_star.xml b/java/com/android/dialer/dialpadview/res/layout/dialpad_key_star.xml
index d288475..6897d26 100644
--- a/java/com/android/dialer/dialpadview/res/layout/dialpad_key_star.xml
+++ b/java/com/android/dialer/dialpadview/res/layout/dialpad_key_star.xml
@@ -13,14 +13,19 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
+
+<!-- A layout representing key "*" in the dialpad -->
 <com.android.dialer.dialpadview.DialpadKeyButton
-  xmlns:android="http://schemas.android.com/apk/res/android"
-  android:id="@+id/star"
-  style="@style/DialpadKeyButtonStyle">
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/star"
+    style="@style/DialpadKeyButtonStyle">
+
   <LinearLayout
-    style="@style/DialpadKeyInternalLayoutStyle">
+      android:id="@+id/dialpad_key_layout"
+      style="@style/DialpadKeyInternalLayoutStyle">
+
     <com.android.dialer.dialpadview.DialpadTextView
-      android:id="@+id/dialpad_key_number"
-      style="@style/DialpadKeyStarStyle"/>
+        android:id="@+id/dialpad_key_number"
+        style="@style/DialpadKeyStarStyle"/>
   </LinearLayout>
 </com.android.dialer.dialpadview.DialpadKeyButton>
diff --git a/java/com/android/dialer/dialpadview/res/layout/dialpad_key_zero.xml b/java/com/android/dialer/dialpadview/res/layout/dialpad_key_zero.xml
index 943ae48..8d9c7b2 100644
--- a/java/com/android/dialer/dialpadview/res/layout/dialpad_key_zero.xml
+++ b/java/com/android/dialer/dialpadview/res/layout/dialpad_key_zero.xml
@@ -14,24 +14,21 @@
      limitations under the License.
 -->
 
-<!-- A layout representing the zero key in the dialpad, with the plus sign shifted up because it is
-     smaller than a regular letter -->
+<!-- A layout representing key "0" in the dialpad -->
 <com.android.dialer.dialpadview.DialpadKeyButton
-  xmlns:android="http://schemas.android.com/apk/res/android"
-  android:id="@+id/zero"
-  style="@style/DialpadKeyButtonStyle">
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/zero"
+    style="@style/DialpadKeyButtonStyle">
 
-  <LinearLayout style="@style/DialpadKeyInternalLayoutStyle">
-
-    <!-- Note in the referenced styles that we assign hard widths to these components
-         because we want them to line up vertically when we arrange them in an MxN grid -->
+  <LinearLayout
+      android:id="@+id/dialpad_key_layout"
+      style="@style/DialpadKeyInternalLayoutStyle">
 
     <com.android.dialer.dialpadview.DialpadTextView
-      android:id="@+id/dialpad_key_number"
-      style="@style/DialpadBottomKeyNumberStyle"/>
-
+        android:id="@+id/dialpad_key_number"
+        style="@style/DialpadBottomKeyNumberStyle"/>
     <TextView
-      android:id="@+id/dialpad_key_letters"
-      style="@style/DialpadKeyLettersStyle"/>
+        android:id="@+id/dialpad_key_letters"
+        style="@style/DialpadKeyLettersStyle"/>
   </LinearLayout>
 </com.android.dialer.dialpadview.DialpadKeyButton>