Skip to content

Commit c5eb211

Browse files
Abbondanzometa-codesync[bot]
authored andcommitted
Encapsulate Android 15 text-layout reflection (#58681)
Summary: Pull Request resolved: #58681 Wrap the three Android 15 text-layout APIs behind typed private helpers that mirror their platform signatures. This keeps reflection isolated and makes replacing each helper with a direct API call a local change once all targets compile against Android 15 or later. Changelog: [Internal] ___ Differential Revision: D121810388 fbshipit-source-id: d46ac4fd38c4151564fd3f868883fcd470a75924
1 parent 57f4080 commit c5eb211

1 file changed

Lines changed: 35 additions & 10 deletions

File tree

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

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,8 @@ internal object TextLayoutManager {
116116

117117
private val tagToSpannableCache = ConcurrentHashMap<Int, Spannable>()
118118

119-
// Lazily cached methods for showing glyph ink that overhangs the start of a line (API 35+).
120-
// Reflection is needed because some internal targets compile against an SDK older than 35.
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.
121121
private val setUseBoundsForWidthMethod: java.lang.reflect.Method? by lazy {
122122
try {
123123
StaticLayout.Builder::class
@@ -128,6 +128,16 @@ internal object TextLayoutManager {
128128
}
129129
}
130130

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+
131141
private val setShiftDrawingOffsetForStartOverhangMethod: java.lang.reflect.Method? by lazy {
132142
try {
133143
StaticLayout.Builder::class
@@ -141,6 +151,19 @@ internal object TextLayoutManager {
141151
}
142152
}
143153

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+
144167
private val computeDrawingBoundingBoxMethod: java.lang.reflect.Method? by lazy {
145168
try {
146169
Layout::class.java.getMethod("computeDrawingBoundingBox")
@@ -149,6 +172,13 @@ internal object TextLayoutManager {
149172
}
150173
}
151174

175+
private fun computeDrawingBoundingBox(layout: Layout): RectF? =
176+
try {
177+
computeDrawingBoundingBoxMethod?.invoke(layout) as? RectF
178+
} catch (_: ReflectiveOperationException) {
179+
null
180+
}
181+
152182
fun setCachedSpannableForTag(reactTag: Int, sp: Spannable) {
153183
tagToSpannableCache[reactTag] = sp
154184
}
@@ -919,12 +949,7 @@ internal object TextLayoutManager {
919949
return 0
920950
}
921951

922-
val drawingBounds =
923-
try {
924-
computeDrawingBoundingBoxMethod?.invoke(layout) as? RectF
925-
} catch (_: ReflectiveOperationException) {
926-
null
927-
} ?: return 0
952+
val drawingBounds = computeDrawingBoundingBox(layout) ?: return 0
928953

929954
return ceil(drawingBounds.right - layout.width).toInt().coerceAtLeast(0)
930955
}
@@ -966,8 +991,8 @@ internal object TextLayoutManager {
966991
// right, so createLayout reserves that space in a second pass while preserving the EXACT Yoga
967992
// measurement returned to the caller.
968993
if (Build.VERSION.SDK_INT >= VERSION_CODE_VANILLA_ICE_CREAM) {
969-
setUseBoundsForWidthMethod?.invoke(builder, enableStartOverhang)
970-
setShiftDrawingOffsetForStartOverhangMethod?.invoke(builder, enableStartOverhang)
994+
setUseBoundsForWidth(builder, enableStartOverhang)
995+
setShiftDrawingOffsetForStartOverhang(builder, enableStartOverhang)
971996
}
972997

973998
return builder.build()

0 commit comments

Comments
 (0)