Android: textAlign: "justify" is silently ignored on ColorOS 15 (Realme/OPPO) — RN sets JUSTIFICATION_MODE_INTER_WORD but the OEM discards it
Dieses Issue hat noch niemand übernommen.
Bewertung
- Schwierigkeit
- 4/5
- Geschätzter Aufwand
- 3-5 Tage
- Anfängerfreundlichkeit
- 45/100
- Issue-Typ
- Bug
- Klarheit
- Klar beschrieben
- Aktivitätsstatus
- Aktiv
- Tech-Stack
- android, javascript, react-native
Rechercherichtung
The issue is in the Android text layout, specifically in TextLayoutManager.getTextJustificationMode() and StaticLayout.Builder.setJustificationMode(). Start by examining the reproducer's App.tsx and the measurement logic using onTextLayout. Look at the React Native source code in ReactTextView and the TextLayoutManager to see how justification is set. The goal is to detect when justification is ignored on ColorOS and provide a fallback or warning.
Vom Indexierungsmodell aus dem Issue-Text verfasst.
Beschreibung
Description
On ColorOS 15 (Realme / OPPO), textAlign: "justify" on a plain <Text> renders
left-aligned. There is no error, no warning and no fallback — the app has no way to know
justification did not happen.
React Native itself does the right thing. TextLayoutManager.getTextJustificationMode()
maps the "justified" alignment attribute to Layout.JUSTIFICATION_MODE_INTER_WORD, and
createLayout() passes it to StaticLayout.Builder.setJustificationMode() on API >= 26.
The OEM text engine accepts the call and does not apply it.
This is not the New Architecture path: enablePreparedTextLayout defaults to false, so
this goes through the shared ReactTextView / StaticLayout route.
It is also not a library, font or styling problem. I tested 13 variants on both devices —
bare justify, textBreakStrategy simple/highQuality/balanced, with and without
lineHeight, four fonts (system default, sans-serif, and two bundled asset fonts),
includeFontPadding: false, android_hyphenationFrequency: "normal", and nested <Text>.
- Stock Android: all 13 justify correctly.
- ColorOS 15: none justify, including the simplest possible case — a plain
<Text>
with onlyfontSizeandtextAlign: "justify", no custom font and no other styling.
A textAlign: "left" control was included throughout and correctly reads unjustified on
both devices, confirming the measurement distinguishes the two states.
Why this is worth an RN-level issue even though the root cause is the OEM: apps
currently have no way to detect that justification was dropped, so the only options are an
OEM allowlist or shipping silently broken layout. Either a way to query whether
justification was actually applied, or a documented caveat on textAlign, would let apps
fall back deliberately.
Steps to reproduce
-
Clone and install the reproducer:
git clone https://github.com/ilalgtc/ColorOSJustifyRepro.git cd ColorOSJustifyRepro npm install -
Run it on a ColorOS 15 device (tested: Realme RMX3686, Android 15, API 35):
npx react-native run-androidEverything is in
App.tsx. There is one screen and no extra dependency. -
Read the summary line at the top of the screen. On ColorOS it reports:
JUSTIFIED on this device: none -
Look at probe A — a plain
<Text>with onlyfontSizeand
textAlign: "justify", no custom font, no HTML renderer, no third-party library.
It renders left-aligned with a ragged right edge and reportsNOT JUSTIFIED,
with a shortfall of tens of px against the container. -
Run the same build on stock Android (an emulator is enough). The summary line
reports:JUSTIFIED on this device: A, B, C, D, E, F, Gand probe A renders flush to both margins, reporting
shortfall 0.0px.
Each probe renders the same paragraph in the same container and measures itself via
onTextLayout, so the screen prints its own verdict — nothing has to be judged by eye.
Probe Z is a control using textAlign: "left". It must read NOT JUSTIFIED on
every device, including stock Android. It is there to prove the measurement can tell
the two states apart rather than always reporting "justified" — if Z ever reads
JUSTIFIED, the measurement is broken and the app says so on screen.
React Native Version
0.87.1
Affected Platforms
Runtime - Android
Output of npx @react-native-community/cli info
System:
OS: macOS 26.3
CPU: (8) arm64 Apple M2
Memory: 123.92 MB / 16.00 GB
Shell:
version: "5.9"
path: /bin/zsh
Binaries:
Node:
version: 24.3.0
path: /Users/kaushal/.nvm/versions/node/v24.3.0/bin/node
Yarn:
version: 1.22.22
path: /opt/homebrew/bin/yarn
npm:
version: 11.4.2
path: /Users/kaushal/.nvm/versions/node/v24.3.0/bin/npm
Watchman:
version: 2026.01.12.00
path: /opt/homebrew/bin/watchman
Managers:
CocoaPods:
version: 1.16.2
path: /opt/homebrew/bin/pod
SDKs:
iOS SDK:
Platforms:
- DriverKit 25.2
- iOS 26.2
- macOS 26.2
- tvOS 26.2
- visionOS 26.2
- watchOS 26.2
Android SDK: Not Found
IDEs:
Android Studio: 2026.1 AI-261.26222.65.2613.16025427
Xcode:
version: 26.2/17C52
path: /usr/bin/xcodebuild
Languages:
Java:
version: 17.0.18
path: /usr/bin/javac
Ruby:
version: 2.6.10
path: /usr/bin/ruby
npmPackages:
"@react-native-community/cli":
installed: 20.2.0
wanted: 20.2.0
react:
installed: 19.2.3
wanted: 19.2.3
react-native:
installed: 0.87.1
wanted: 0.87.1
react-native-macos: Not Found
npmGlobalPackages:
"*react-native*": Not Found
Android:
hermesEnabled: true
newArchEnabled: true
iOS:
hermesEnabled: Not found
newArchEnabled: false
Stacktrace or Logs
No crash. This is a rendering/layout defect, so the "log" is the line geometry the
reproducer measures with onTextLayout and prints on screen.
Reproducer: probe A = <Text style={{ fontSize: 16, textAlign: "justify" }}>
Probe Z = the same text with textAlign: "left" (control)
React Native 0.87.1, new architecture enabled.
--- Emulator, stock Android 16 (API 36) -----------------------------------------
Summary line: "JUSTIFIED on this device: A, B, C, D, E, F, G"
A (justify only) box 394.7 · 12 lines · shortfall 0.0px · overflow 4.3px
widths 398.6, 395.9, 397.5, 398.6, 398.9, 397.2, ...
Z (control, left) box 394.7 · 12 lines · shortfall 41.8px · overflow 0.0px
widths 352.9, 369.4, 358.6, 385.5, 354.9, 376.7, ...
Probes B-G report identical geometry to A. The control behaves as expected.
--- Realme RMX3686, ColorOS 15, Android 15 (API 35) -----------------------------
Summary line: "JUSTIFIED on this device: none"
A (justify only) box <FILL> · <FILL> lines · shortfall <FILL>px · overflow <FILL>px
widths <FILL>
Z (control, left) box <FILL> · <FILL> lines · shortfall <FILL>px · overflow <FILL>px
widths <FILL>
---------------------------------------------------------------------------------
Probe A on ColorOS measures tens of px short and its line widths vary line to line —
the signature of left-aligned text — while the identical probe on stock Android is
flush to within 0.0px. Probe Z is unjustified on both, confirming the measurement
separates the two states rather than always reporting "justified".
Secondary observation: where justification does work, lines measure ~4px WIDER than
their container (overflow 4.3px above), which clips the trailing glyph. Visible on
stock Android too and independent of the ColorOS problem.
MANDATORY Reproducer
https://github.com/kaushaldarji29/ColorOSJustifyRepro
Screenshots and Videos
- Vorherrschende Sprache
- C++
- Sterne
- 127k
- Forks
- 25.3k
- PR-Merge-Kennzahlen
- Keine gemergten PRs in 30 T.
Beitragsleitfaden
Erste Schritte
- Lesen Sie das ganze Issue und danach den Beitragsleitfaden des Projekts.
- Schreiben Sie ins Issue, dass Sie es übernehmen — das erspart doppelte Arbeit.
- Forken Sie das Repository und arbeiten Sie in einem Branch.
- Öffnen Sie einen Pull Request, der die Issue-Nummer nennt.
Mehr aus react/react-native
-
Needs: Author Feedback Needs: Repro
Schwierigkeit 1/5 Unter einer Stunde Anfängerfreundlichkeit 92/100
react/react-native#58621 · 1 Kommentar ·
-
Needs: Author Feedback Needs: Repro
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 85/100
react/react-native#58610 · 1 Kommentar ·
-
Needs: Triage :mag:
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 82/100
react/react-native#58565 · 1 Kommentar · 2 Reaktionen ·
-
Needs: Author Feedback Needs: Repro
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 88/100
react/react-native#58555 · 5 Kommentare · 2 Reaktionen ·
-
Needs: Attention Needs: Repro
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 85/100
react/react-native#58526 · 2 Kommentare ·
Alle Issues in react/react-native
Ähnliche Issues
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 75/100
flutter-webrtc/flutter-webrtc#2206 ·
-
litertlm-android AAR ships no consumer ProGuard rules → "mid == null" SIGABRT in minified apps Offen
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 70/100
google-ai-edge/LiteRT-LM#3739 ·
-
Component: GLib
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 70/100
-
Mute ydb/tests/functional/dstool/test_canonical_requests.py.Test.test_group_take_snapshot in main Offenai_reviewed
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 70/100
ydb-platform/ydb#53974 · 3 Kommentare ·
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 70/100
google/libultrahdr#485 ·