From e6db8a4d31fa5566e287254121969a589cdfaf97 Mon Sep 17 00:00:00 2001 From: conradchen Date: Wed, 10 Nov 2021 12:10:52 -0500 Subject: [PATCH] [TopAppBar] Fix text alignment of multi-line title in collapsing toolbar In single line mode, we implement the expanded title alignment by calculating the expected x-coordinate of expanded title and translate the canvas so the title will be aligned. However, when maxLines > 1, the static layout will always occupy the full available width, therefore the text alignment need to be done by the static layout instead. Provides text alignment other than NORMAL when it's in multi-line mode to solve the issue. Resolves https://github.com/material-components/material-components-android/issues/1276 PiperOrigin-RevId: 408895140 --- .../internal/CollapsingTextHelper.java | 24 +++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/lib/java/com/google/android/material/internal/CollapsingTextHelper.java b/lib/java/com/google/android/material/internal/CollapsingTextHelper.java index 190cef839a0..81614e7dade 100644 --- a/lib/java/com/google/android/material/internal/CollapsingTextHelper.java +++ b/lib/java/com/google/android/material/internal/CollapsingTextHelper.java @@ -17,7 +17,9 @@ package com.google.android.material.internal; import static androidx.core.util.Preconditions.checkNotNull; +import static android.text.Layout.Alignment.ALIGN_CENTER; import static android.text.Layout.Alignment.ALIGN_NORMAL; +import static android.text.Layout.Alignment.ALIGN_OPPOSITE; import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP; import static java.lang.Math.max; import static java.lang.Math.min; @@ -36,6 +38,7 @@ import android.os.Build.VERSION_CODES; import androidx.core.view.GravityCompat; import androidx.core.view.ViewCompat; +import android.text.Layout.Alignment; import android.text.StaticLayout; import android.text.TextPaint; import android.text.TextUtils; @@ -820,7 +823,7 @@ private boolean shouldDrawMultiline() { private void drawMultilineTransition(@NonNull Canvas canvas, float currentExpandedX, float y) { int originalAlpha = textPaint.getAlpha(); - // positon expanded text appropriately + // position expanded text appropriately canvas.translate(currentExpandedX, y); // Expanded text textPaint.setAlpha((int) (expandedTextBlend * originalAlpha)); @@ -967,11 +970,13 @@ private void calculateUsingTextSize(final float textSize, boolean forceRecalcula private StaticLayout createStaticLayout(int maxLines, float availableWidth, boolean isRtl) { StaticLayout textLayout = null; try { + // In multiline mode, the text alignment should be controlled by the static layout. + Alignment textAlignment = maxLines == 1 ? ALIGN_NORMAL : getMultilineTextLayoutAlignment(); textLayout = StaticLayoutBuilderCompat.obtain(text, textPaint, (int) availableWidth) .setEllipsize(TruncateAt.END) .setIsRtl(isRtl) - .setAlignment(ALIGN_NORMAL) + .setAlignment(textAlignment) .setIncludePad(false) .setMaxLines(maxLines) .setLineSpacing(lineSpacingAdd, lineSpacingMultiplier) @@ -984,6 +989,21 @@ private StaticLayout createStaticLayout(int maxLines, float availableWidth, bool return checkNotNull(textLayout); } + private Alignment getMultilineTextLayoutAlignment() { + int absoluteGravity = + GravityCompat.getAbsoluteGravity( + expandedTextGravity, + isRtl ? ViewCompat.LAYOUT_DIRECTION_RTL : ViewCompat.LAYOUT_DIRECTION_LTR); + switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) { + case Gravity.CENTER_HORIZONTAL: + return ALIGN_CENTER; + case Gravity.RIGHT: + return isRtl ? ALIGN_NORMAL : ALIGN_OPPOSITE; + default: + return isRtl ? ALIGN_OPPOSITE : ALIGN_NORMAL; + } + } + private void ensureExpandedTexture() { if (expandedTitleTexture != null || expandedBounds.isEmpty() || TextUtils.isEmpty(textToDraw)) { return;