Skip to content

Commit a86976e

Browse files
Restore ReactTextView.setMinimumFontSize() as deprecated and add setMinimumFontScale()
1 parent d089183 commit a86976e

5 files changed

Lines changed: 60 additions & 7 deletions

File tree

‎packages/react-native/ReactAndroid/api/ReactAndroid.api‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6041,6 +6041,7 @@ public class com/facebook/react/views/text/ReactTextView : androidx/appcompat/wi
60416041
public fun setLetterSpacing (F)V
60426042
public fun setLinkifyMask (I)V
60436043
public fun setMinimumFontScale (F)V
6044+
public fun setMinimumFontSize (F)V
60446045
public fun setNumberOfLines (I)V
60456046
public fun setOverflow (Ljava/lang/String;)V
60466047
public fun setSpanned (Landroid/text/Spannable;)V

‎packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextView.java‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ public class ReactTextView extends AppCompatTextView implements ReactCompoundVie
7171
private @Nullable TextUtils.TruncateAt mEllipsizeLocation;
7272
private boolean mAdjustsFontSizeToFit;
7373
private float mFontSize;
74+
private float mMinimumFontSize;
7475
private float mMinimumFontScale;
7576
private float mLetterSpacing;
7677
private int mLinkifyMaskType;
@@ -132,6 +133,7 @@ private void initView() {
132133
mShouldAdjustSpannableFontSize = false;
133134
mEllipsizeLocation = TextUtils.TruncateAt.END;
134135
mFontSize = Float.NaN;
136+
mMinimumFontSize = Float.NaN;
135137
mMinimumFontScale = Float.NaN;
136138
mLetterSpacing = 0.f;
137139
mOverflow = Overflow.VISIBLE;
@@ -238,6 +240,7 @@ protected void onDraw(Canvas canvas) {
238240
YogaMeasureMode.EXACTLY,
239241
getHeight(),
240242
YogaMeasureMode.EXACTLY,
243+
mMinimumFontSize,
241244
mMinimumFontScale,
242245
mNumberOfLines,
243246
getIncludeFontPadding(),
@@ -540,6 +543,15 @@ public void setFontSize(float fontSize) {
540543
applyTextAttributes();
541544
}
542545

546+
/**
547+
* @deprecated Use {@link #setMinimumFontScale(float)} instead.
548+
*/
549+
@Deprecated
550+
public void setMinimumFontSize(float minimumFontSize) {
551+
mMinimumFontSize = minimumFontSize;
552+
mShouldAdjustSpannableFontSize = true;
553+
}
554+
543555
public void setMinimumFontScale(float minimumFontScale) {
544556
mMinimumFontScale = minimumFontScale;
545557
mShouldAdjustSpannableFontSize = true;

‎packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextViewManager.kt‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,8 +169,13 @@ public constructor(
169169
)
170170
view.setSpanned(spanned)
171171

172+
val minimumFontSize: Float =
173+
paragraphAttributes.getDouble(TextLayoutManager.PA_KEY_MINIMUM_FONT_SIZE).toFloat()
174+
@Suppress("DEPRECATION") view.setMinimumFontSize(minimumFontSize)
172175
val minimumFontScale: Float =
173-
paragraphAttributes.getDouble(TextLayoutManager.PA_KEY_MINIMUM_FONT_SCALE).toFloat()
176+
if (paragraphAttributes.contains(TextLayoutManager.PA_KEY_MINIMUM_FONT_SCALE))
177+
paragraphAttributes.getDouble(TextLayoutManager.PA_KEY_MINIMUM_FONT_SCALE).toFloat()
178+
else Float.NaN
174179
view.setMinimumFontScale(minimumFontScale)
175180

176181
// Clear any stale PreparedLayout from a previous update

‎packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManager.kt‎

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -95,9 +95,10 @@ internal object TextLayoutManager {
9595
const val PA_KEY_ADJUST_FONT_SIZE_TO_FIT: Int = 3
9696
const val PA_KEY_INCLUDE_FONT_PADDING: Int = 4
9797
const val PA_KEY_HYPHENATION_FREQUENCY: Int = 5
98-
const val PA_KEY_MINIMUM_FONT_SCALE: Int = 6
98+
const val PA_KEY_MINIMUM_FONT_SIZE: Int = 6
9999
const val PA_KEY_TEXT_ALIGN_VERTICAL: Int = 8
100100
const val PA_KEY_TEXT_WIDTH_MODE: Int = 9
101+
const val PA_KEY_MINIMUM_FONT_SCALE: Int = 10
101102

102103
private val TAG: String = TextLayoutManager::class.java.simpleName
103104

@@ -1167,6 +1168,10 @@ internal object TextLayoutManager {
11671168
val justificationMode = getTextJustificationMode(alignmentAttr)
11681169

11691170
if (adjustFontSizeToFit) {
1171+
val minimumFontSize =
1172+
if (paragraphAttributes.contains(PA_KEY_MINIMUM_FONT_SIZE))
1173+
paragraphAttributes.getDouble(PA_KEY_MINIMUM_FONT_SIZE).toFloat()
1174+
else Float.NaN
11701175
val minimumFontScale =
11711176
if (paragraphAttributes.contains(PA_KEY_MINIMUM_FONT_SCALE))
11721177
paragraphAttributes.getDouble(PA_KEY_MINIMUM_FONT_SCALE).toFloat()
@@ -1178,6 +1183,7 @@ internal object TextLayoutManager {
11781183
YogaMeasureMode.EXACTLY,
11791184
height,
11801185
heightYogaMeasureMode,
1186+
minimumFontSize,
11811187
minimumFontScale,
11821188
maximumNumberOfLines,
11831189
includeFontPadding,
@@ -1337,6 +1343,7 @@ internal object TextLayoutManager {
13371343
widthYogaMeasureMode: YogaMeasureMode,
13381344
height: Float,
13391345
heightYogaMeasureMode: YogaMeasureMode,
1346+
minimumFontSizeAttr: Float,
13401347
minimumFontScale: Float,
13411348
maximumNumberOfLines: Int,
13421349
includeFontPadding: Boolean,
@@ -1356,12 +1363,16 @@ internal object TextLayoutManager {
13561363
currentFontSize = max(currentFontSize, span.size)
13571364
}
13581365

1359-
// The smallest font size is the largest font size scaled by minimumFontScale, floored at 4dp
1360-
// to match the iOS implementation.
1366+
// An explicit minimum font size wins over minimumFontScale, which is applied to the largest
1367+
// font size in the spannable. The 4dp floor matches the iOS implementation.
13611368
val absoluteMinimumFontSize = 4.dpToPx().toInt()
13621369
val minimumFontSize =
1363-
if (minimumFontScale.isNaN() || minimumFontScale <= 0f) absoluteMinimumFontSize
1364-
else max((minimumFontScale * currentFontSize).toInt(), absoluteMinimumFontSize)
1370+
when {
1371+
!minimumFontSizeAttr.isNaN() -> minimumFontSizeAttr.toInt()
1372+
!minimumFontScale.isNaN() && minimumFontScale > 0f ->
1373+
max((minimumFontScale * currentFontSize).toInt(), absoluteMinimumFontSize)
1374+
else -> absoluteMinimumFontSize
1375+
}
13651376
currentFontSize = max(currentFontSize, minimumFontSize)
13661377

13671378
var intervalStart = minimumFontSize

‎packages/react-native/ReactAndroid/src/test/java/com/facebook/react/views/text/TextLayoutManagerMinimumFontScaleTest.kt‎

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,24 @@ class TextLayoutManagerMinimumFontScaleTest {
8989
assertThat(largestFontSize(text)).isEqualTo(4.dpToPx().toInt())
9090
}
9191

92+
@Test
93+
fun `explicit minimumFontSize is used as the floor`() {
94+
val text = spannableWithFontSize(LARGE_FONT_SIZE)
95+
96+
adjustToUnsatisfiableHeight(text, minimumFontSize = 12f, minimumFontScale = Float.NaN)
97+
98+
assertThat(largestFontSize(text)).isEqualTo(12)
99+
}
100+
101+
@Test
102+
fun `explicit minimumFontSize takes precedence over minimumFontScale`() {
103+
val text = spannableWithFontSize(LARGE_FONT_SIZE)
104+
105+
adjustToUnsatisfiableHeight(text, minimumFontSize = 12f, minimumFontScale = 0.5f)
106+
107+
assertThat(largestFontSize(text)).isEqualTo(12)
108+
}
109+
92110
@Test
93111
fun `text that already fits is not shrunk`() {
94112
val text = spannableWithFontSize(LARGE_FONT_SIZE)
@@ -99,6 +117,7 @@ class TextLayoutManagerMinimumFontScaleTest {
99117
YogaMeasureMode.EXACTLY,
100118
10_000f,
101119
YogaMeasureMode.EXACTLY,
120+
Float.NaN,
102121
0.5f,
103122
ReactConstants.UNSET,
104123
true,
@@ -113,13 +132,18 @@ class TextLayoutManagerMinimumFontScaleTest {
113132
}
114133

115134
// Uses a height no font size can satisfy so the text is shrunk all the way to the minimum.
116-
private fun adjustToUnsatisfiableHeight(text: SpannableString, minimumFontScale: Float) {
135+
private fun adjustToUnsatisfiableHeight(
136+
text: SpannableString,
137+
minimumFontScale: Float,
138+
minimumFontSize: Float = Float.NaN,
139+
) {
117140
TextLayoutManager.adjustSpannableFontToFit(
118141
text,
119142
10_000f,
120143
YogaMeasureMode.EXACTLY,
121144
1f,
122145
YogaMeasureMode.EXACTLY,
146+
minimumFontSize,
123147
minimumFontScale,
124148
ReactConstants.UNSET,
125149
true,

0 commit comments

Comments
 (0)