facebook / react-native

A framework for building native applications using React
https://reactnative.dev
MIT License
118.75k stars 24.29k forks source link

Text with adjustFontSizeToFit and numberOfLine equal to 1 leads to text being cut off or having extra width #47045

Open itsramiel opened 2 days ago

itsramiel commented 2 days ago

Description

I have a row of the 3 items. Each item contains two texts. I want that the left text shrinks in size if needed, so I have set flexShrink: 1, adjustFontSizeToFit, and numberOfLines={1}. While it works for some, it breaks for others in two ways:

  1. The text is for some reason cut off Android: Screenshot 2024-10-16 at 9 32 53 AM iOS: Screenshot 2024-10-16 at 9 33 51 AM

  2. The text is taking more space than needed: Android: Screenshot 2024-10-16 at 9 34 44 AM iOS: doesnt seem to happen here

Steps to reproduce

  1. Clone the repo
  2. Run the app on iOS/Android

React Native Version

0.75.4

Affected Platforms

Runtime - Android, Runtime - iOS

Output of npx react-native info

System:
  OS: macOS 14.6.1
  CPU: (14) arm64 Apple M3 Max
  Memory: 98.53 MB / 36.00 GB
  Shell:
    version: "5.9"
    path: /bin/zsh
Binaries:
  Node:
    version: 20.11.1
    path: ~/.nvm/versions/node/v20.11.1/bin/node
  Yarn:
    version: 3.6.4
    path: ~/.nvm/versions/node/v20.11.1/bin/yarn
  npm:
    version: 10.2.4
    path: ~/.nvm/versions/node/v20.11.1/bin/npm
  Watchman:
    version: 2024.08.26.00
    path: /opt/homebrew/bin/watchman
Managers:
  CocoaPods:
    version: 1.14.3
    path: /Users/itsramiel/.rbenv/shims/pod
SDKs:
  iOS SDK:
    Platforms:
      - DriverKit 23.5
      - iOS 17.5
      - macOS 14.5
      - tvOS 17.5
      - visionOS 1.2
      - watchOS 10.5
  Android SDK: Not Found
IDEs:
  Android Studio: 2024.1 AI-241.18034.62.2412.12266719
  Xcode:
    version: 15.4/15F31d
    path: /usr/bin/xcodebuild
Languages:
  Java:
    version: 17.0.10
    path: /usr/bin/javac
  Ruby:
    version: 3.0.0
    path: /Users/itsramiel/.rbenv/shims/ruby
npmPackages:
  "@react-native-community/cli": Not Found
  react:
    installed: 18.3.1
    wanted: 18.3.1
  react-native:
    installed: 0.75.4
    wanted: 0.75.4
  react-native-macos: Not Found
npmGlobalPackages:
  "*react-native*": Not Found
Android:
  hermesEnabled: true
  newArchEnabled: false
iOS:
  hermesEnabled: true
  newArchEnabled: false

### Stacktrace or Logs

```text
No Crash or failure

Reproducer

https://github.com/itsramiel/SingleLineText

Screenshots and Videos

iOS Android
cortinico commented 1 day ago

@itsramiel is this happening also on New Architecture?

@coado @j-piasecki do you have any context on this one?

itsramiel commented 1 day ago

Yes same behavior on new arch. Can be test on new-arch branch

j-piasecki commented 1 day ago

@cortinico Nothing from the top of my head, but we can take a closer look at this.

j-piasecki commented 1 day ago

This is an interesting one. The code for scaling down the font size when adjustsFontSizeToFit effectively doesn't run for single-character text. On Android it relies on line breaks to check whether the text doesn't fit in the container and single character cannot be broken. On iOS it relies on truncatedGlyphRangeInLineFragmentForGlyphAtIndex which seems to always return NSNotFound when the string has only one character.

itsramiel commented 1 day ago

@j-piasecki Interesting finding. That is consistent with the seen effect, where it only happens to single character in the screenshots above.

Do you have a fix in mind, is it easy to implement?

j-piasecki commented 23 hours ago

@itsramiel I'm not sure whether it's the perfect solution, but I've opened a PR which is fixing the problem in the repro you've provided. Could you verify that it works for you?

itsramiel commented 1 minute ago

@j-piasecki

I am not sure what the easiest way to test it, but I copied your changes to my react-native files in my node_modules. iOS worked but Android didnt.

I tried with a nightly version of react native and got the same result. However, it could easily be that I am copying the code wrongly or missing something, so I would love to know the easiest way to test this.