TextView
elegantTextView
Some languages/scripts (such as Arabic, Lao, Myanmar, Tamil, Gujarati, Kannada, Malayalam, Odia, Telugu, and Thai) have larger vertical metrics than other most languages. To make these languages more readable, we can set TextView
's elegantTextView
to true:
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:elegantTextHeight="true"
android:text="@string/my_complex_script_text" />
Notice the different between using elegantTextView
and not:
⛔️ android:elegantTextView="false" | ✅ android:elegantTextView="true" |
---|---|
Behavior Changes in Apps Targeting Android 15
For apps targeting Android 15 (API Level 35), elegantTextView
is set to true by default.
You can disable elegantTextView
by setting it to true (using compact font). However, it is unlikely to be supported in upcoming releases.
No Break Text
In Android 15, we can preserve a given portion of text in the same line to improve readibility. The first way to do this is by using <nobreak>
tag in string resource:
<resources>
<string name="long_text">Learn all things about Android in <nobreak>Android Notebook!</nobreak></string>
</resources>
Notice the different between using <nobreak>
and not:
⛔️ Without <nobreak> | ✅ With <nobreak> |
---|---|
The second way to achieve this by using createNoBreakSpan()
method:
import android.app.Activity
import android.text.Spannable
import android.text.SpannableString
import android.text.style.LineBreakConfigSpan
import android.widget.TextView
val normalText = "Learn all things about Android in "
val noBreakText = "Android Notebook!"
val finalText = normalText + noBreakText
val span = SpannableString(finalText)
span.setSpan(
LineBreakConfigSpan.createNoBreakSpan(),
finalText.indexOf(noBreakText),
finalText.indexOf(noBreakText) + noBreakText.length,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE,
)
activity.findViewById<TextView>(R.id.text_view).setText(span, TextView.BufferType.SPANNABLE)
No Hyphen Text
In Android 15, we can disable hyphenation for certain portion of text. The first way to do this is by using <nohyphen>
tag in string resource:
<resources>
<string name="long_text_hyphen">The 1984 World Snooker Championship was a ranking professional snooker tournament that took place between 21 April and 7 May at the <nohyphen>Crucible Theatre</nohyphen> in Sheffield, England.</string>
</resources>
Notice the different between using <nohyphen>
and not (in "Crucible Theater" text):
⛔️ Without <nohyphen> | ✅ With <nohyphen> |
---|---|
The second way to achieve this by using createNoHyphenationSpan()
method:
import android.app.Activity
import android.text.Spannable
import android.text.SpannableString
import android.text.style.LineBreakConfigSpan
import android.widget.TextView
val normalText = "The 1984 World Snooker Championship was a ranking professional snooker tournament that took place between 21 April and 7 May at the "
val noHyphenText = "Crucible Theatre"
val normalText2 = " in Sheffield, England."
val finalString = normalText + noHyphenText + normalText2
val span = SpannableString(finalString)
span.setSpan(
LineBreakConfigSpan.createNoHyphenationSpan(),
finalString.indexOf(noHyphenText),
finalString.indexOf(noHyphenText) + noHyphenText.length,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
)
activity.findViewById<TextView>(R.id.text_view).setText(span, TextView.BufferType.SPANNABLE)
Justification Mode
Android 8.0 (API Level 26) introduced a TextView property to customize our text's justification mode. There are 3 available justification modes:
Justification Mode (for layout resource) | Constant | API Level |
---|---|---|
none | JUSTIFICATION_MODE_NONE | 26 |
inter_word | JUSTIFICATION_MODE_INTER_WORD | 26 |
inter_character | JUSTIFICATION_MODE_INTER_CHARACTER | 35 |
Here's how each justification mode differs from each other:
With English Text | With Japanese Text |
---|---|
JUSTIFICATION_MODE_INTER_CHARACTER
, introduced in Android 15, is especially useful for languages that use the whitespace character for segmentation, such as Chinese and Japanese.
The first way of setting justification mode is by using justificationMode
attribute in our layout resource:
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:justificationMode="inter_character"
android:text="@string/my_long_text" />
The second way of setting justification mode is by using setJustificationMode()
method:
import android.app.Activity
import android.graphics.text.LineBreaker
import android.os.Build
import android.widget.TextView
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
activity.findViewById<TextView>(R.id.textview1).justificationMode = LineBreaker.JUSTIFICATION_MODE_INTER_WORD
}
Line Break Configuration
Android 13 (API Level 33) introduced a way to wrap Japanese and Korean text by Bunsetsu (the smallest unit of words that sounds natural) or phrases, instead of character. Here's the difference between phrase-based line breaks and not:
⛔️ Normal line break | ✅ Phrase-based line break |
---|---|
(Image Source: developer.android.com) |
Phrase-based line break works well for short text, but they don't really work well for long ones. So, in Android 15 (API Level 35), a new line break configuration was introduced that will automatically choose the best line break configuration for your text. Here's an example of how this new configuration will wrap your text based on its length:
Short Text (Will use LINE_BREAK_WORD_STYLE_PHRASE ) | Long Text (Will use LINE_BREAK_WORD_STYLE_NONE ) |
---|---|
(Image Source: developer.android.com) |
That leaves us with these 3 line break configurations:
Line Break Configuration (for layout resource) | Constant | API Level | Description |
---|---|---|---|
none | LINE_BREAK_WORD_STYLE_NONE | 33 | No line-break word style is used for line breaking. |
phrase | LINE_BREAK_WORD_STYLE_PHRASE | 33 | Line breaking is based on phrases, which results in text wrapping only on meaningful words. Support for this line-break word style depends on locale. If the current locale does not support phrase-based text wrapping, this setting has no effect. |
? | LINE_BREAK_WORD_STYLE_AUTO | 35 | A special value for the line breaking word style option. The auto option for the line break word style does some heuristics based on locales and line count. In Android 15 (API Level 35), auto option does followings: - If at least one locale in the locale list contains Korean script, this option is equivalent to LINE_BREAK_WORD_STYLE_PHRASE . - If not, then if at least one locale in the locale list contains Japanese script, this option is equivalent to LINE_BREAK_WORD_STYLE_PHRASE if the result of its line count is less than 5 lines. - Otherwise, this option is equivalent to LINE_BREAK_WORD_STYLE_NONE . |
You can either set your TextView
's line break configuration by using the lineBreakWordStyle
attribute:
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:lineBreakWordStyle="phrase"
android:text="@string/my_short_japanese_text" />
Or programmatically by using setLineBreakWordStyle()
method:
import android.app.Activity
import android.graphics.text.LineBreakConfig
import android.os.Build
import android.widget.TextView
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
activity.findViewById<TextView>(R.id.textview).lineBreakWordStyle = LineBreakConfig.LINE_BREAK_WORD_STYLE_PHRASE
}