From b642e150b2b7bba2f5694984c7ec56f5b8b1fa1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20=C5=81opaci=C5=84ski?= Date: Fri, 18 Sep 2026 11:40:17 +0200 Subject: [PATCH] Rebuild the TextView Layout before drawing text effects on Android ReactTextView.onDraw paints CanvasEffectSpans (underline, strikethrough) only when getLayout() is non-null. TextView drops its Layout in setText and rebuilds it in onMeasure, and Fabric measures a view only when its frame changed, so a text state update that keeps the frame (a decoration or color change on a text of the same size) reaches onDraw with no Layout and the decorations are skipped until something else re-measures the view. Rebuild the Layout at the current size before painting; TextView.onDraw would build one for the plain text anyway. --- .../com/facebook/react/views/text/ReactTextView.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextView.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextView.java index eed89a0aa56..fb58329875e 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextView.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextView.java @@ -257,6 +257,15 @@ protected void onDraw(Canvas canvas) { if (spanned != null) { Layout layout = getLayout(); + if (layout == null && getWidth() > 0 && getHeight() > 0) { + // setText drops the Layout and Fabric re-measures only on a frame change, so a text + // update that kept the frame reaches onDraw without one and the effects below would be + // skipped. Rebuild it here; TextView.onDraw would build one for the text anyway. + measure( + MeasureSpec.makeMeasureSpec(getWidth(), MeasureSpec.EXACTLY), + MeasureSpec.makeMeasureSpec(getHeight(), MeasureSpec.EXACTLY)); + layout = getLayout(); + } if (layout != null) { CanvasEffectSpan[] drawSpans = spanned.getSpans(0, spanned.length(), CanvasEffectSpan.class);