diff --git a/core/api/current.txt b/core/api/current.txt index 688b66e7c00c0..1bc3e81d9b06e 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -950,6 +950,7 @@ package android { field public static final int letterSpacing = 16843958; // 0x10104b6 field public static final int level = 16844032; // 0x1010500 field public static final int lineBreakStyle = 16844365; // 0x101064d + field public static final int lineBreakWordStyle = 16844366; // 0x101064e field public static final int lineHeight = 16844159; // 0x101057f field public static final int lineSpacingExtra = 16843287; // 0x1010217 field public static final int lineSpacingMultiplier = 16843288; // 0x1010218 @@ -17581,12 +17582,16 @@ package android.graphics.text { public final class LineBreakConfig { ctor public LineBreakConfig(); method public int getLineBreakStyle(); - method public void set(@Nullable android.graphics.text.LineBreakConfig); + method public int getLineBreakWordStyle(); + method public void set(@NonNull android.graphics.text.LineBreakConfig); method public void setLineBreakStyle(int); + method public void setLineBreakWordStyle(int); field public static final int LINE_BREAK_STYLE_LOOSE = 1; // 0x1 field public static final int LINE_BREAK_STYLE_NONE = 0; // 0x0 field public static final int LINE_BREAK_STYLE_NORMAL = 2; // 0x2 field public static final int LINE_BREAK_STYLE_STRICT = 3; // 0x3 + field public static final int LINE_BREAK_WORD_STYLE_NONE = 0; // 0x0 + field public static final int LINE_BREAK_WORD_STYLE_PHRASE = 1; // 0x1 } public class LineBreaker { diff --git a/core/java/android/text/PrecomputedText.java b/core/java/android/text/PrecomputedText.java index ce63376a6d631..be66db2a4c055 100644 --- a/core/java/android/text/PrecomputedText.java +++ b/core/java/android/text/PrecomputedText.java @@ -363,6 +363,9 @@ public class PrecomputedText implements Spannable { public String toString() { int lineBreakStyle = (mLineBreakConfig != null) ? mLineBreakConfig.getLineBreakStyle() : LineBreakConfig.LINE_BREAK_STYLE_NONE; + int lineBreakWordStyle = (mLineBreakConfig != null) + ? mLineBreakConfig.getLineBreakWordStyle() + : LineBreakConfig.LINE_BREAK_WORD_STYLE_NONE; return "{" + "textSize=" + mPaint.getTextSize() + ", textScaleX=" + mPaint.getTextScaleX() @@ -376,6 +379,7 @@ public class PrecomputedText implements Spannable { + ", breakStrategy=" + mBreakStrategy + ", hyphenationFrequency=" + mHyphenationFrequency + ", lineBreakStyle=" + lineBreakStyle + + ", lineBreakWordStyle=" + lineBreakWordStyle + "}"; } }; diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 0fe06befa7893..a710a80125828 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -350,6 +350,7 @@ import java.util.function.Supplier; * @attr ref android.R.styleable#TextView_breakStrategy * @attr ref android.R.styleable#TextView_hyphenationFrequency * @attr ref android.R.styleable#TextView_lineBreakStyle + * @attr ref android.R.styleable#TextView_lineBreakWordStyle * @attr ref android.R.styleable#TextView_autoSizeTextType * @attr ref android.R.styleable#TextView_autoSizeMinTextSize * @attr ref android.R.styleable#TextView_autoSizeMaxTextSize @@ -458,6 +459,13 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener private static final int FLOATING_TOOLBAR_SELECT_ALL_REFRESH_DELAY = 500; + // The default value of the line break style. + private static final int DEFAULT_LINE_BREAK_STYLE = LineBreakConfig.LINE_BREAK_STYLE_NONE; + + // The default value of the line break word style. + private static final int DEFAULT_LINE_BREAK_WORD_STYLE = + LineBreakConfig.LINE_BREAK_WORD_STYLE_NONE; + /** * This change ID enables the fallback text line spacing (line height) for BoringLayout. * @hide @@ -1450,6 +1458,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener a.getInt(attr, LineBreakConfig.LINE_BREAK_STYLE_NONE)); break; + case com.android.internal.R.styleable.TextView_lineBreakWordStyle: + mLineBreakConfig.setLineBreakWordStyle( + a.getInt(attr, LineBreakConfig.LINE_BREAK_WORD_STYLE_NONE)); + break; + case com.android.internal.R.styleable.TextView_autoSizeTextType: mAutoSizeTextType = a.getInt(attr, AUTO_SIZE_TEXT_TYPE_NONE); break; @@ -3982,6 +3995,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener float mLetterSpacing = 0; String mFontFeatureSettings = null; String mFontVariationSettings = null; + boolean mHasLineBreakStyle = false; + boolean mHasLineBreakWordStyle = false; + int mLineBreakStyle = DEFAULT_LINE_BREAK_STYLE; + int mLineBreakWordStyle = DEFAULT_LINE_BREAK_WORD_STYLE; @Override public String toString() { @@ -4012,6 +4029,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener + " mLetterSpacing:" + mLetterSpacing + "\n" + " mFontFeatureSettings:" + mFontFeatureSettings + "\n" + " mFontVariationSettings:" + mFontVariationSettings + "\n" + + " mHasLineBreakStyle:" + mHasLineBreakStyle + "\n" + + " mHasLineBreakWordStyle:" + mHasLineBreakWordStyle + "\n" + + " mLineBreakStyle:" + mLineBreakStyle + "\n" + + " mLineBreakWordStyle:" + mLineBreakWordStyle + "\n" + "}"; } } @@ -4059,6 +4080,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener com.android.internal.R.styleable.TextAppearance_fontFeatureSettings); sAppearanceValues.put(com.android.internal.R.styleable.TextView_fontVariationSettings, com.android.internal.R.styleable.TextAppearance_fontVariationSettings); + sAppearanceValues.put(com.android.internal.R.styleable.TextView_lineBreakStyle, + com.android.internal.R.styleable.TextAppearance_lineBreakStyle); + sAppearanceValues.put(com.android.internal.R.styleable.TextView_lineBreakWordStyle, + com.android.internal.R.styleable.TextAppearance_lineBreakWordStyle); } /** @@ -4174,6 +4199,16 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener case com.android.internal.R.styleable.TextAppearance_fontVariationSettings: attributes.mFontVariationSettings = appearance.getString(attr); break; + case com.android.internal.R.styleable.TextAppearance_lineBreakStyle: + attributes.mHasLineBreakStyle = true; + attributes.mLineBreakStyle = + appearance.getInt(attr, attributes.mLineBreakStyle); + break; + case com.android.internal.R.styleable.TextAppearance_lineBreakWordStyle: + attributes.mHasLineBreakWordStyle = true; + attributes.mLineBreakWordStyle = + appearance.getInt(attr, attributes.mLineBreakWordStyle); + break; default: } } @@ -4239,8 +4274,45 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (attributes.mFontVariationSettings != null) { setFontVariationSettings(attributes.mFontVariationSettings); } + + if (attributes.mHasLineBreakStyle || attributes.mHasLineBreakWordStyle) { + updateLineBreakConfigFromTextAppearance(attributes.mHasLineBreakStyle, + attributes.mHasLineBreakWordStyle, attributes.mLineBreakStyle, + attributes.mLineBreakWordStyle); + } } + /** + * Updates the LineBreakConfig from the TextAppearance. + * + * This method updates the given line configuration from the TextAppearance. This method will + * request new layout if line break config has been changed. + * + * @param isLineBreakStyleSpecified true if the line break style is specified. + * @param isLineBreakWordStyleSpecified true if the line break word style is specified. + * @param lineBreakStyle the value of the line break style in the TextAppearance. + * @param lineBreakWordStyle the value of the line break word style in the TextAppearance. + */ + private void updateLineBreakConfigFromTextAppearance(boolean isLineBreakStyleSpecified, + boolean isLineBreakWordStyleSpecified, + @LineBreakConfig.LineBreakStyle int lineBreakStyle, + @LineBreakConfig.LineBreakWordStyle int lineBreakWordStyle) { + boolean updated = false; + if (isLineBreakStyleSpecified && mLineBreakConfig.getLineBreakStyle() != lineBreakStyle) { + mLineBreakConfig.setLineBreakStyle(lineBreakStyle); + updated = true; + } + if (isLineBreakWordStyleSpecified + && mLineBreakConfig.getLineBreakWordStyle() != lineBreakWordStyle) { + mLineBreakConfig.setLineBreakWordStyle(lineBreakWordStyle); + updated = true; + } + if (updated && mLayout != null) { + nullLayouts(); + requestLayout(); + invalidate(); + } + } /** * Get the default primary {@link Locale} of the text in this TextView. This will always be * the first member of {@link #getTextLocales()}. @@ -4797,18 +4869,29 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener /** * Sets line break configuration indicates which strategy needs to be used when calculating the - * text wrapping. There are thee strategies for the line break style(lb): + * text wrapping. + *
+ * There are two types of line break rules that can be configured at the same time. One is
+ * line break style(lb) and the other is line break word style(lw). The line break style
+ * affects rule-based breaking. The line break word style affects dictionary-based breaking
+ * and provide phrase-based breaking opportunities. There are several types for the
+ * line break style:
* {@link LineBreakConfig#LINE_BREAK_STYLE_LOOSE},
* {@link LineBreakConfig#LINE_BREAK_STYLE_NORMAL} and
* {@link LineBreakConfig#LINE_BREAK_STYLE_STRICT}.
- * The default value of the line break style is {@link LineBreakConfig#LINE_BREAK_STYLE_NONE},
- * which means no line break style is specified.
+ * The type for the line break word style is
+ * {@link LineBreakConfig#LINE_BREAK_WORD_STYLE_PHRASE}.
+ * The default values of the line break style and the line break word style are
+ * {@link LineBreakConfig#LINE_BREAK_STYLE_NONE} and
+ * {@link LineBreakConfig#LINE_BREAK_WORD_STYLE_NONE} respectively, indicating that no line
+ * breaking rules are specified.
* See
* the line-break property
*
* @param lineBreakConfig the line break config for text wrapping.
*/
public void setLineBreakConfig(@NonNull LineBreakConfig lineBreakConfig) {
+ Objects.requireNonNull(lineBreakConfig);
if (mLineBreakConfig.equals(lineBreakConfig)) {
return;
}
@@ -4855,7 +4938,13 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
mTextDir = params.getTextDirection();
mBreakStrategy = params.getBreakStrategy();
mHyphenationFrequency = params.getHyphenationFrequency();
- mLineBreakConfig.set(params.getLineBreakConfig());
+ if (params.getLineBreakConfig() != null) {
+ mLineBreakConfig.set(params.getLineBreakConfig());
+ } else {
+ // Set default value if the line break config in the PrecomputedText.Params is null.
+ mLineBreakConfig.setLineBreakStyle(DEFAULT_LINE_BREAK_STYLE);
+ mLineBreakConfig.setLineBreakWordStyle(DEFAULT_LINE_BREAK_WORD_STYLE);
+ }
if (mLayout != null) {
nullLayouts();
requestLayout();
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index e232d858bb434..69fdea44caa85 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -5030,6 +5030,10 @@