From 19d05000bcc273f781a85ce41530f604fead268e Mon Sep 17 00:00:00 2001 From: conradchen Date: Mon, 11 Apr 2022 13:07:27 -0400 Subject: [PATCH] [Button] Fix icon position with multiline text When the icon gravity is textTop, we are using the smaller one of the calculated height from text paint and the text layout height to decide the icon position. This is wrong when there are multiple lines of text since the text paint is always single line and always shorter than the actual height. Fixes this by returning the actual layout height whenever there are multiple lines of text to fix the issue. Resolves https://github.com/material-components/material-components-android/issues/2619 PiperOrigin-RevId: 440923733 --- .../material/button/MaterialButton.java | 26 ++++++++++++------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/lib/java/com/google/android/material/button/MaterialButton.java b/lib/java/com/google/android/material/button/MaterialButton.java index 1741c8dc745..f10b0d1d6a5 100644 --- a/lib/java/com/google/android/material/button/MaterialButton.java +++ b/lib/java/com/google/android/material/button/MaterialButton.java @@ -20,6 +20,8 @@ import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP; import static com.google.android.material.theme.overlay.MaterialThemeOverlay.wrap; +import static java.lang.Math.max; +import static java.lang.Math.min; import android.content.Context; import android.content.res.ColorStateList; @@ -593,13 +595,15 @@ private void updateIconPosition(int buttonWidth, int buttonHeight) { int localIconSize = iconSize == 0 ? icon.getIntrinsicHeight() : iconSize; int newIconTop = - (buttonHeight - - getTextHeight() - - getPaddingTop() - - localIconSize - - iconPadding - - getPaddingBottom()) - / 2; + max( + 0, // Always put the icon on top if the content height is taller than the button. + (buttonHeight + - getTextHeight() + - getPaddingTop() + - localIconSize + - iconPadding + - getPaddingBottom()) + / 2); if (iconTop != newIconTop) { iconTop = newIconTop; @@ -617,10 +621,14 @@ private int getTextWidth() { buttonText = getTransformationMethod().getTransformation(buttonText, this).toString(); } - return Math.min((int) textPaint.measureText(buttonText), getLayout().getEllipsizedWidth()); + return min((int) textPaint.measureText(buttonText), getLayout().getEllipsizedWidth()); } private int getTextHeight() { + if (getLineCount() > 1) { + // If it's multi-line, return the internal text layout's height. + return getLayout().getHeight(); + } Paint textPaint = getPaint(); String buttonText = getText().toString(); if (getTransformationMethod() != null) { @@ -632,7 +640,7 @@ private int getTextHeight() { Rect bounds = new Rect(); textPaint.getTextBounds(buttonText, 0, buttonText.length(), bounds); - return Math.min(bounds.height(), getLayout().getHeight()); + return min(bounds.height(), getLayout().getHeight()); } private boolean isLayoutRTL() {