react-native
react-native copied to clipboard
Lines getting cut-off on Android devices with small font sizes
Description
When device font size is set to small words in certain configuration of parent views get cut-off (see reproducer). Our users just started reporting in the last month it so I believe it was introduced in 0.79.
Steps to reproduce
UI bug, see attached screenshots.
React Native Version
0.79.1
Affected Platforms
Runtime - Android, Build - MacOS
Output of npx @react-native-community/cli info
$npx @react-native-community/cli info
info Fetching system and libraries information...
System:
OS: macOS 15.3.2
CPU: (12) arm64 Apple M3 Pro
Memory: 112.06 MB / 36.00 GB
Shell:
version: "5.9"
path: /bin/zsh
Binaries:
Node:
version: 23.7.0
path: /opt/homebrew/bin/node
Yarn:
version: 1.22.22
path: /opt/homebrew/bin/yarn
npm:
version: 11.2.0
path: ~/node_modules/.bin/npm
Watchman:
version: 2025.02.17.00
path: /opt/homebrew/bin/watchman
Managers:
CocoaPods:
version: 1.14.3
path: /Users/johanlndll/.gem/ruby/3.1.4/bin/pod
SDKs:
iOS SDK:
Platforms:
- DriverKit 24.0
- iOS 18.0
- macOS 15.0
- tvOS 18.0
- visionOS 2.0
- watchOS 11.0
Android SDK:
API Levels:
- "30"
- "34"
- "35"
Build Tools:
- 30.0.3
- 33.0.0
- 33.0.1
- 34.0.0
- 35.0.0
System Images:
- android-30 | Google Play ARM 64 v8a
- android-34 | Google APIs ARM 64 v8a
- android-35 | Google APIs ARM 64 v8a
- android-35 | Google Play ARM 64 v8a
Android NDK: Not Found
IDEs:
Android Studio: 2024.2 AI-242.21829.142.2421.12409432
Xcode:
version: 16.0/16A242d
path: /usr/bin/xcodebuild
Languages:
Java:
version: 17.0.10
path: /usr/bin/javac
Ruby:
version: 3.1.4
path: /Users/johanlndll/.rubies/ruby-3.1.4/bin/ruby
npmPackages:
"@react-native-community/cli": Not Found
react:
installed: 19.1.0
wanted: 19.1.0
react-native: Not Found
react-native-macos: Not Found
npmGlobalPackages:
"*react-native*": Not Found
Android:
hermesEnabled: Not found
newArchEnabled: Not found
iOS:
hermesEnabled: Not found
newArchEnabled: Not found
Stacktrace or Logs
UI bug.
MANDATORY Reproducer
https://github.com/facebook/react-native/pull/50915
Screenshots and Videos
Emulator is Pixel_9_API_35
With the issue:
Without the issue:
[!WARNING] Missing reproducer: We could not detect a reproducible example in your issue report. Reproducers are mandatory and we can accept only one of those as a valid reproducer:
- For majority of bugs: send us a Pull Request with the RNTesterPlayground.js edited to reproduce your bug.
- If your bug is UI related: a Snack
- If your bug is build/upgrade related: a project using our Reproducer Template
You can read more about about it on our website: How to report a bug.
Linked it in original, but in case it helps the bot this is pull request: https://github.com/facebook/react-native/pull/50915
@LA-Johan Thanks for opening the issue! While reviewing the output of npx @react-native-community/cli info, we couldn’t determine if the new architecture is enabled, could you let us know whether the problem occurs on both the old architecture and the new architecture? This will help us narrow things down. Thanks!
@devanshsaini11 this is only on new architecture!
If anyone has found a workaround that would be great too. This breaks some of our core flows for users with different font sizes making some text completely unreadable.
@devanshsaini11 do you know which classes I might investigate on the Android side to potentially fix this? If I find the time I'd be willing to try and fix this but would appreciate some pointers.
According to my understanding looking into TextLayoutManager or CustomLineHeightSpan might help you.
Haven't had time to try and fix yet but can report issue persists on 0.79.2. Would appreciate any help from the team, accessibility is broken for some of our users who use larger font sizes.
@devanshsaini11 I spent some time debugging this and I've narrowed it down to this code here
When we have a small font size, the width will be smaller than the boring.width on a second measure, causing a StaticLayout to be used, with normal font size the width will be a 1 pixel larger, and a BoringLayout is used instead.
-- SMALL FONT SIZE --
05-13 23:18:02.285 16069 16102 D TextLayoutManager: Row cutoff boring.width: 155, unconstrainedWidth: false, width: 1027.5
05-13 23:18:02.286 16069 16102 D TextLayoutManager: Row cutoff boring.width: 155, unconstrainedWidth: false, width: 132.0
05-13 23:18:02.287 16069 16102 D TextLayoutManager: Row cutoff boring.width: 155, unconstrainedWidth: false, width: 133.0
-- NORMAL FONT SIZE --
05-13 23:18:15.135 16166 16204 D TextLayoutManager: Row cutoff boring.width: 179, unconstrainedWidth: false, width: 1027.5
05-13 23:18:15.136 16166 16204 D TextLayoutManager: Row cutoff boring.width: 179, unconstrainedWidth: false, width: 180.0
05-13 23:18:15.137 16166 16204 D TextLayoutManager: Row cutoff boring.width: 179, unconstrainedWidth: false, width: 180.0
I've tried to find the source of the width but I'm getting lost in the bridging code between js and android, any pointers on where to look next?
05-14 08:55:53.810 20205 20241 D TextLayoutManager: at com.facebook.react.views.text.TextLayoutManager.logIfRelevant(TextLayoutManager.java:1041)
05-14 08:55:53.810 20205 20241 D TextLayoutManager: at com.facebook.react.views.text.TextLayoutManager.createLayout(TextLayoutManager.java:462)
05-14 08:55:53.810 20205 20241 D TextLayoutManager: at com.facebook.react.views.text.TextLayoutManager.createLayout(TextLayoutManager.java:609)
05-14 08:55:53.810 20205 20241 D TextLayoutManager: at com.facebook.react.views.text.TextLayoutManager.measureText(TextLayoutManager.java:725)
05-14 08:55:53.810 20205 20241 D TextLayoutManager: at com.facebook.react.views.text.ReactTextViewManager.measure(ReactTextViewManager.java:214)
05-14 08:55:53.810 20205 20241 D TextLayoutManager: at com.facebook.react.fabric.mounting.MountingManager.measureMapBuffer(MountingManager.java:415)
05-14 08:55:53.810 20205 20241 D TextLayoutManager: at com.facebook.react.fabric.FabricUIManager.measureMapBuffer(FabricUIManager.java:642)
05-14 08:55:53.810 20205 20241 D TextLayoutManager: at com.facebook.jni.NativeRunnable.run(Native Method)
05-14 08:55:53.810 20205 20241 D TextLayoutManager: at android.os.Handler.handleCallback(Handler.java:959)
05-14 08:55:53.810 20205 20241 D TextLayoutManager: at android.os.Handler.dispatchMessage(Handler.java:100)
05-14 08:55:53.810 20205 20241 D TextLayoutManager: at com.facebook.react.bridge.queue.MessageQueueThreadHandler.dispatchMessage(MessageQueueThreadHandler.kt:21)
05-14 08:55:53.810 20205 20241 D TextLayoutManager: at android.os.Looper.loopOnce(Looper.java:232)
05-14 08:55:53.810 20205 20241 D TextLayoutManager: at android.os.Looper.loop(Looper.java:317)
05-14 08:55:53.810 20205 20241 D TextLayoutManager: at com.facebook.react.bridge.queue.MessageQueueThreadImpl$Companion.startNewBackgroundThread$lambda$1(MessageQueueThreadImpl.kt:175)
05-14 08:55:53.810 20205 20241 D TextLayoutManager: at com.facebook.react.bridge.queue.MessageQueueThreadImpl$Companion.$r8$lambda$ldnZnqelhYFctGaUKkOKYj5rxo4(Unknown Source:0)
05-14 08:55:53.810 20205 20241 D TextLayoutManager: at com.facebook.react.bridge.queue.MessageQueueThreadImpl$Companion$$ExternalSyntheticLambda0.run(D8$$SyntheticClass:0)
05-14 08:55:53.810 20205 20241 D TextLayoutManager: at java.lang.Thread.run(Thread.java:1012)
Also, I haven't had any luck attaching a debugger to the Android code, any guides I find seem to be for generic react-native project, is there something different I need to do to debug here?
Confirmed this was fixed with the new logic for rounding in https://github.com/facebook/react-native/commit/1fe3ff86c364fad023ad1e426f26608699314339
Note that the previous incorrect logic goes back all the way to legacy arch (ReactTextShadowNode), so I don't think the underlying bug is new, but it relies on getting "unlucky" with pixel grid rounding, so there are different cosmic butterflies that can influence this.
| Before | After |
|---|---|
Actually it looks like this can still happen non-deterministically. I will see if I can take a closer look. Though there is a new text stack coming for Android meant to eliminate the source of some of these issues.
@NickGerleman thank you for looking into this. I know you said it doesn't fix the entire issue, but which version of RN will https://github.com/facebook/react-native/commit/1fe3ff86c364fad023ad1e426f26608699314339 go live in?
This issue dates back to 2017, and you could try this workaround: https://github.com/facebook/react-native/issues/15114#issuecomment-2422537975
Our app started experiencing this issue after upgrading from version 0.72 to 0.77 and enabling the new architecture. We've already received multiple user reports. They all encountered the problem after adjusting the system font size or enabling bold text. This issue did not occur in the previous version.
请问这个问题解决了吗
Just checking in — has anyone figured out a good way to handle this?
Looking at the commits I think some fixes for this are going live with 0.81.0, is that fair to say @NickGerleman ?
https://github.com/user-attachments/assets/8003ccfb-e9db-4520-9bd3-fffba367e342
I just initialized a new React Native project with version 0.81.0-rc.3, and simulated the issue by increasing the system font size and weight on the device.
After changing the font size and weight, I observed that some text (usually the last character) gets truncated or disappears, which is consistent with what my users (on Xiaomi and OPPO devices) are experiencing.
Unfortunately, since this mainly happens on end users' devices, I can only provide screenshots, not a full reproduction. @NickGerleman @LA-Johan
@WenBin0201 thank you for checking. I hope words at least stop disappearing completely, bummer it's not fully resolved yet.
my workaround:
import { Platform, StyleSheet, Text } from 'react-native';
if (Platform.OS === 'android') {
const styles = StyleSheet.create({
defaultText: {
fontFamily: '',
// workaround
fontWeight: 'normal',
},
});
const oldRender = (Text as any).render;
(Text as any).render = function (props: any, ...args: any[]) {
return oldRender.call(
this,
{
...props,
style: [styles.defaultText, props.style],
},
...args,
);
};
}
@huanguolin 这样的话 字重就没了 我现在是设置了 robot字体 并且禁止缩放
@huanguolin 这样的话 字重就没了 我现在是设置了 robot字体 并且禁止缩放
In my case, the fontWeight setting in the code is fine. However, when I set zoom to be disabled, it doesn’t work in version 0.77 (it works in 0.80). Moreover, my users won’t accept this.
Add a scenario: This problem can also occur on some tablet devices with very good screen resolution, such as screens with a resolution of 3200 * 2136 and 308PPI
mmm seems to occur when some specific length occurs, depending on font props, adding eg style Platform.OS === 'android' && { paddingHorizontal/paddingRight: 0.001 }, helps for, at least one of our cases, but if it helps for all 🤷
@OskarAtJoint I also apply this trick as a backup solution.
Confirmed this was fixed with the new logic for rounding in 1fe3ff8
Note that the previous incorrect logic goes back all the way to legacy arch (ReactTextShadowNode), so I don't think the underlying bug is new, but it relies on getting "unlucky" with pixel grid rounding, so there are different cosmic butterflies that can influence this.
Before After
![]()
Could you please cherry pick this to 0.79?
https://github.com/user-attachments/assets/7647ed8a-26c5-47c2-8e7d-47da965e347f 这RN的新架构 兼容性太差了
不仅切字 窗口的宽高还计算不准确
