From 8e956a041144855e06e597f30179039ed4a77f24 Mon Sep 17 00:00:00 2001 From: Allen Su Date: Thu, 11 May 2023 11:57:45 +0000 Subject: [PATCH] [TextView] add setLineBreakConfig() API in DynamicLayout Bug: 281778721 Test: atest DynamicLayoutTest Change-Id: I6b3805ec1562b02a6881629dd52f435aa1cb7e53 --- core/api/current.txt | 2 ++ core/java/android/text/DynamicLayout.java | 38 ++++++++++++++++++++++- core/java/android/widget/TextView.java | 12 +++++-- 3 files changed, 48 insertions(+), 4 deletions(-) diff --git a/core/api/current.txt b/core/api/current.txt index 5ad5fa45e5511..d180270f90931 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -47172,6 +47172,7 @@ package android.text { method public int getBottomPadding(); method public int getEllipsisCount(int); method public int getEllipsisStart(int); + method @NonNull public android.graphics.text.LineBreakConfig getLineBreakConfig(); method public boolean getLineContainsTab(int); method public int getLineCount(); method public int getLineDescent(int); @@ -47193,6 +47194,7 @@ package android.text { method @NonNull public android.text.DynamicLayout.Builder setHyphenationFrequency(int); method @NonNull public android.text.DynamicLayout.Builder setIncludePad(boolean); method @NonNull public android.text.DynamicLayout.Builder setJustificationMode(int); + method @NonNull public android.text.DynamicLayout.Builder setLineBreakConfig(@NonNull android.graphics.text.LineBreakConfig); method @NonNull public android.text.DynamicLayout.Builder setLineSpacing(float, @FloatRange(from=0.0) float); method @NonNull public android.text.DynamicLayout.Builder setTextDirection(@NonNull android.text.TextDirectionHeuristic); method @NonNull public android.text.DynamicLayout.Builder setUseLineSpacingFromFallbacks(boolean); diff --git a/core/java/android/text/DynamicLayout.java b/core/java/android/text/DynamicLayout.java index cd767541e13a3..ba08f2541f794 100644 --- a/core/java/android/text/DynamicLayout.java +++ b/core/java/android/text/DynamicLayout.java @@ -23,6 +23,7 @@ import android.annotation.Nullable; import android.compat.annotation.UnsupportedAppUsage; import android.graphics.Paint; import android.graphics.Rect; +import android.graphics.text.LineBreakConfig; import android.os.Build; import android.text.method.OffsetMapping; import android.text.style.ReplacementSpan; @@ -88,6 +89,7 @@ public class DynamicLayout extends Layout { b.mBreakStrategy = Layout.BREAK_STRATEGY_SIMPLE; b.mHyphenationFrequency = Layout.HYPHENATION_FREQUENCY_NONE; b.mJustificationMode = Layout.JUSTIFICATION_MODE_NONE; + b.mLineBreakConfig = LineBreakConfig.NONE; return b; } @@ -267,6 +269,22 @@ public class DynamicLayout extends Layout { return this; } + /** + * Set the line break configuration. The line break will be passed to native used for + * calculating the text wrapping. The default value of the line break style is + * {@link LineBreakConfig#LINE_BREAK_STYLE_NONE} + * + * @param lineBreakConfig the line break configuration for text wrapping. + * @return this builder, useful for chaining. + * @see android.widget.TextView#setLineBreakStyle + * @see android.widget.TextView#setLineBreakWordStyle + */ + @NonNull + public Builder setLineBreakConfig(@NonNull LineBreakConfig lineBreakConfig) { + mLineBreakConfig = lineBreakConfig; + return this; + } + /** * Build the {@link DynamicLayout} after options have been set. * @@ -298,6 +316,7 @@ public class DynamicLayout extends Layout { private int mJustificationMode; private TextUtils.TruncateAt mEllipsize; private int mEllipsizedWidth; + private LineBreakConfig mLineBreakConfig = LineBreakConfig.NONE; private final Paint.FontMetricsInt mFontMetricsInt = new Paint.FontMetricsInt(); @@ -344,7 +363,7 @@ public class DynamicLayout extends Layout { this(base, display, paint, width, align, TextDirectionHeuristics.FIRSTSTRONG_LTR, spacingmult, spacingadd, includepad, Layout.BREAK_STRATEGY_SIMPLE, Layout.HYPHENATION_FREQUENCY_NONE, - Layout.JUSTIFICATION_MODE_NONE, ellipsize, ellipsizedWidth); + Layout.JUSTIFICATION_MODE_NONE, LineBreakConfig.NONE, ellipsize, ellipsizedWidth); } /** @@ -365,6 +384,7 @@ public class DynamicLayout extends Layout { boolean includepad, @BreakStrategy int breakStrategy, @HyphenationFrequency int hyphenationFrequency, @JustificationMode int justificationMode, + @NonNull LineBreakConfig lineBreakConfig, @Nullable TextUtils.TruncateAt ellipsize, @IntRange(from = 0) int ellipsizedWidth) { super(createEllipsizer(ellipsize, display), @@ -381,6 +401,7 @@ public class DynamicLayout extends Layout { mBreakStrategy = breakStrategy; mJustificationMode = justificationMode; mHyphenationFrequency = hyphenationFrequency; + mLineBreakConfig = lineBreakConfig; generate(b); @@ -396,6 +417,7 @@ public class DynamicLayout extends Layout { mBreakStrategy = b.mBreakStrategy; mJustificationMode = b.mJustificationMode; mHyphenationFrequency = b.mHyphenationFrequency; + mLineBreakConfig = b.mLineBreakConfig; generate(b); } @@ -608,6 +630,7 @@ public class DynamicLayout extends Layout { .setBreakStrategy(mBreakStrategy) .setHyphenationFrequency(mHyphenationFrequency) .setJustificationMode(mJustificationMode) + .setLineBreakConfig(mLineBreakConfig) .setAddLastLineLineSpacing(!islast); reflowed.generate(b, false /*includepad*/, true /*trackpad*/); @@ -1209,6 +1232,18 @@ public class DynamicLayout extends Layout { return mInts.getValue(line, ELLIPSIS_COUNT); } + /** + * Gets the {@link LineBreakconfig} used in this DynamicLayout. + * Use this only to consult the LineBreakConfig's properties and not + * to change them. + * + * @return The line break config in this DynamicLayout. + */ + @NonNull + public LineBreakConfig getLineBreakConfig() { + return mLineBreakConfig; + } + private CharSequence mBase; private CharSequence mDisplay; private ChangeWatcher mWatcher; @@ -1220,6 +1255,7 @@ public class DynamicLayout extends Layout { private int mBreakStrategy; private int mHyphenationFrequency; private int mJustificationMode; + private LineBreakConfig mLineBreakConfig; private PackedIntVector mInts; private PackedObjectVector mObjects; diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index db7d48471d9df..3181df500f1d9 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -10686,6 +10686,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener boolean useSaved) { Layout result = null; if (useDynamicLayout()) { + final boolean autoPhraseBreaking = isAutoPhraseBreakingEnabled(); final DynamicLayout.Builder builder = DynamicLayout.Builder.obtain(mText, mTextPaint, wantWidth) .setDisplayText(mTransformed) @@ -10697,6 +10698,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener .setBreakStrategy(mBreakStrategy) .setHyphenationFrequency(mHyphenationFrequency) .setJustificationMode(mJustificationMode) + .setLineBreakConfig(LineBreakConfig.getLineBreakConfig( + mLineBreakStyle, mLineBreakWordStyle, autoPhraseBreaking)) .setEllipsize(getKeyListener() == null ? effectiveEllipsize : null) .setEllipsizedWidth(ellipsisWidth); result = builder.build(); @@ -10741,9 +10744,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } } if (result == null) { - final boolean autoPhraseBreaking = - !mUserSpeficiedLineBreakwordStyle && FeatureFlagUtils.isEnabled(mContext, - FeatureFlagUtils.SETTINGS_AUTO_TEXT_WRAPPING); + final boolean autoPhraseBreaking = isAutoPhraseBreakingEnabled(); StaticLayout.Builder builder = StaticLayout.Builder.obtain(mTransformed, 0, mTransformed.length(), mTextPaint, wantWidth) .setAlignment(alignment) @@ -10766,6 +10767,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener return result; } + private boolean isAutoPhraseBreakingEnabled() { + return !mUserSpeficiedLineBreakwordStyle && FeatureFlagUtils.isEnabled(mContext, + FeatureFlagUtils.SETTINGS_AUTO_TEXT_WRAPPING); + } + @UnsupportedAppUsage private boolean compressText(float width) { if (isHardwareAccelerated()) return false;