Skip to content

Commit bdfebe5

Browse files
Abbondanzometa-codesync[bot]
authored andcommitted
Use Android 15 text APIs directly (#58719)
Summary: Pull Request resolved: #58719 ReactAndroid now compiles the text layout implementation against Android 15 or later. Call the platform glyph-bounds and start-overhang APIs directly instead of resolving and invoking them through reflection. Changelog: [Internal] Reviewed By: cortinico Differential Revision: D122079801 fbshipit-source-id: 3615d6da450fb13437a814a833a17ad8c669b222
1 parent 4d19c39 commit bdfebe5

1 file changed

Lines changed: 5 additions & 70 deletions

File tree

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

Lines changed: 5 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ package com.facebook.react.views.text
99

1010
import android.content.res.AssetManager
1111
import android.graphics.Color
12-
import android.graphics.RectF
1312
import android.graphics.Typeface
1413
import android.os.Build
1514
import android.text.BoringLayout
@@ -42,7 +41,6 @@ import com.facebook.react.uimanager.PixelUtil
4241
import com.facebook.react.uimanager.PixelUtil.dpToPx
4342
import com.facebook.react.uimanager.PixelUtil.pxToDp
4443
import com.facebook.react.uimanager.ReactAccessibilityDelegate
45-
import com.facebook.react.util.AndroidVersion.VERSION_CODE_VANILLA_ICE_CREAM
4644
import com.facebook.react.views.text.internal.span.CustomLetterSpacingSpan
4745
import com.facebook.react.views.text.internal.span.CustomLineHeightSpan
4846
import com.facebook.react.views.text.internal.span.CustomStyleSpan
@@ -116,69 +114,6 @@ internal object TextLayoutManager {
116114

117115
private val tagToSpannableCache = ConcurrentHashMap<Int, Spannable>()
118116

119-
// These wrappers mirror Android 15 APIs but use reflection because some internal targets still
120-
// compile against Android 14. They return null when the API is unavailable or cannot be invoked.
121-
private val setUseBoundsForWidthMethod: java.lang.reflect.Method? by lazy {
122-
try {
123-
StaticLayout.Builder::class
124-
.java
125-
.getMethod("setUseBoundsForWidth", Boolean::class.javaPrimitiveType)
126-
} catch (_: ReflectiveOperationException) {
127-
null
128-
}
129-
}
130-
131-
private fun setUseBoundsForWidth(
132-
builder: StaticLayout.Builder,
133-
useBoundsForWidth: Boolean,
134-
): StaticLayout.Builder? =
135-
try {
136-
setUseBoundsForWidthMethod?.invoke(builder, useBoundsForWidth) as? StaticLayout.Builder
137-
} catch (_: ReflectiveOperationException) {
138-
null
139-
}
140-
141-
private val setShiftDrawingOffsetForStartOverhangMethod: java.lang.reflect.Method? by lazy {
142-
try {
143-
StaticLayout.Builder::class
144-
.java
145-
.getMethod(
146-
"setShiftDrawingOffsetForStartOverhang",
147-
Boolean::class.javaPrimitiveType,
148-
)
149-
} catch (_: ReflectiveOperationException) {
150-
null
151-
}
152-
}
153-
154-
private fun setShiftDrawingOffsetForStartOverhang(
155-
builder: StaticLayout.Builder,
156-
shiftDrawingOffsetForStartOverhang: Boolean,
157-
): StaticLayout.Builder? =
158-
try {
159-
setShiftDrawingOffsetForStartOverhangMethod?.invoke(
160-
builder,
161-
shiftDrawingOffsetForStartOverhang,
162-
) as? StaticLayout.Builder
163-
} catch (_: ReflectiveOperationException) {
164-
null
165-
}
166-
167-
private val computeDrawingBoundingBoxMethod: java.lang.reflect.Method? by lazy {
168-
try {
169-
Layout::class.java.getMethod("computeDrawingBoundingBox")
170-
} catch (_: ReflectiveOperationException) {
171-
null
172-
}
173-
}
174-
175-
private fun computeDrawingBoundingBox(layout: Layout): RectF? =
176-
try {
177-
computeDrawingBoundingBoxMethod?.invoke(layout) as? RectF
178-
} catch (_: ReflectiveOperationException) {
179-
null
180-
}
181-
182117
fun setCachedSpannableForTag(reactTag: Int, sp: Spannable) {
183118
tagToSpannableCache[reactTag] = sp
184119
}
@@ -940,7 +875,7 @@ internal object TextLayoutManager {
940875
@VisibleForTesting
941876
internal fun getRtlRightOverhang(layout: Layout): Int {
942877
if (
943-
Build.VERSION.SDK_INT < VERSION_CODE_VANILLA_ICE_CREAM ||
878+
Build.VERSION.SDK_INT < Build.VERSION_CODES.VANILLA_ICE_CREAM ||
944879
layout.lineCount == 0 ||
945880
(0 until layout.lineCount).any {
946881
layout.getParagraphDirection(it) != Layout.DIR_RIGHT_TO_LEFT
@@ -949,7 +884,7 @@ internal object TextLayoutManager {
949884
return 0
950885
}
951886

952-
val drawingBounds = computeDrawingBoundingBox(layout) ?: return 0
887+
val drawingBounds = layout.computeDrawingBoundingBox()
953888

954889
return ceil(drawingBounds.right - layout.width).toInt().coerceAtLeast(0)
955890
}
@@ -990,9 +925,9 @@ internal object TextLayoutManager {
990925
// Android shifts negative (left-side) start overhang itself. RTL start overhang is on the
991926
// right, so createLayout reserves that space in a second pass while preserving the EXACT Yoga
992927
// measurement returned to the caller.
993-
if (Build.VERSION.SDK_INT >= VERSION_CODE_VANILLA_ICE_CREAM) {
994-
setUseBoundsForWidth(builder, enableStartOverhang)
995-
setShiftDrawingOffsetForStartOverhang(builder, enableStartOverhang)
928+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM) {
929+
builder.setUseBoundsForWidth(enableStartOverhang)
930+
builder.setShiftDrawingOffsetForStartOverhang(enableStartOverhang)
996931
}
997932

998933
return builder.build()

0 commit comments

Comments
 (0)