Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: text cut off phenomenon on some Android devices like OPPO, Xiaomi and etc #37271

Closed
wants to merge 6 commits into from

Conversation

jcdhlzq
Copy link
Contributor

@jcdhlzq jcdhlzq commented May 5, 2023

Summary: Fix text-cutoff phenomenon in non-Fabric mode on Android device, like #15114, #29259 and many other similar issues that not fixed, and onTextLayout with wrong TextLayout params.

The text-cutoff phenomenon is fixed in native side with a proper layout procedure rather than making a work-around in JavaScript side.

The TextLayout params for onTextLayout callback will be fixed to offer reasonable x and y for each line, especially for RTL languages like Arabic. This problem is shown below.

pixel5-community-lastest

Changelog:

  • [ANDROID] [FIXED] - Fix Text cutoff problem in non-Fabric mode.
  • [ANDROID] [FIXED] - Fix TextLayout params of onTextLayout callback.

Test Plan:

It has been tested on many devices to make sure that the problems are fixed and Text component can work better than that of old version.

The devices are: Pixel 5 Android 13, Xiaomi 10 Pro Android 10, Xiaomi 12 Android 12, Vivo X9L Android 7.1.2, Vivo Y85A Android 8.1, Oppo Reno8 Android13, Oppo A3 Andrroid 10, Oppo R9s Android 6.0.1, Oppo R5m Android 5.1 and Huawei Nova2s Harmony 2.0.

Next two cases on Pixel 5 and Xiaomi 10 Pro wil be shown for proving the effect.

Xiaomi 10 Pro

You could find that text-cutoff problem is well fixed from the screeshots of Xiaomi 10 Pro. And the fixed version works better than the old version on Pixel 5, because the fixed version offers better onTextLayout callback. The evidence will be presented in the next section.

  • Old version

mi10pro-community-origin-vertion

There are many texts cut off.

  • Fixed version

mi10pro-my-vertion

No text cutoff phenomenon and all text are better than the old version.

Pixel 5

Now cases for onTextLayout callback will be presented in this section.

  • Old version

pixel5-community-lastest

The x and y of all the lines is not in correct place.

  • Fixed version

pixel5-fixed-version

Work better!

@facebook-github-bot
Copy link
Contributor

Hi @jcdhlzq!

Thank you for your pull request and welcome to our community.

Action Required

In order to merge any pull request (code, docs, etc.), we require contributors to sign our Contributor License Agreement, and we don't seem to have one on file for you.

Process

In order for us to review and merge your suggested changes, please sign at https://code.facebook.com/cla. If you are contributing on behalf of someone else (eg your employer), the individual CLA may not be sufficient and your employer may need to sign the corporate CLA.

Once the CLA is signed, our tooling will perform checks and validations. Afterwards, the pull request will be tagged with CLA signed. The tagging process may take up to 1 hour after signing. Please give it that time before contacting us about it.

If you have received this in error or have any questions, please contact us at cla@meta.com. Thanks!

@analysis-bot
Copy link

analysis-bot commented May 5, 2023

Platform Engine Arch Size (bytes) Diff
android hermes arm64-v8a 8,733,482 +202
android hermes armeabi-v7a 8,044,661 +200
android hermes x86 9,223,589 +205
android hermes x86_64 9,075,558 +185
android jsc arm64-v8a 9,298,443 +365
android jsc armeabi-v7a 8,487,179 +363
android jsc x86 9,359,616 +373
android jsc x86_64 9,615,702 +366

Base commit: 6d24ee1
Branch: main

@facebook-github-bot
Copy link
Contributor

Thank you for signing our Contributor License Agreement. We can now accept your code for this (and any) Meta Open Source project. Thanks!

@facebook-github-bot facebook-github-bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label May 6, 2023
@gnprice
Copy link
Contributor

gnprice commented May 9, 2023

Interesting, thanks for sending this.

Does this also fix #25481? That's the issue that #15114 was closed as a duplicate of.

@jcdhlzq
Copy link
Contributor Author

jcdhlzq commented May 10, 2023

Interesting, thanks for sending this.

Does this also fix #25481? That's the issue that #15114 was closed as a duplicate of.

Yes, I just tested this issue on the OnePlus device with Roboto font family. I reproduced it and it proved to be fixed with this pr.

The issue #25481 can be reproduced when changing system default font family to Roboto, like the following picture.
oneplus-origin-version

But the same operation don't reproduce the problem.
oneplus-fixed-version

@jcdhlzq
Copy link
Contributor Author

jcdhlzq commented May 16, 2023

Anybody knows what's going on with this pr?

@jcdhlzq
Copy link
Contributor Author

jcdhlzq commented May 23, 2023

Hi, @gnprice ! Do you know what is happening with this PR?

@jcdhlzq
Copy link
Contributor Author

jcdhlzq commented Jun 2, 2023

What's wrong with this PR? @facebook-github-bot

@jcdhlzq
Copy link
Contributor Author

jcdhlzq commented Jun 2, 2023

Do you know what is happening about this PR? @cipolleschi

@jcdhlzq jcdhlzq closed this Jun 2, 2023
@jcdhlzq jcdhlzq reopened this Jun 5, 2023
@cipolleschi
Copy link
Contributor

Hi, what do you mean with "what is happening about this PR?" Are you seeing something unusual or is it just taking longer than usual to get reviewed?

@facebook-github-bot
Copy link
Contributor

@cipolleschi has imported this pull request. If you are a Meta employee, you can view this diff on Phabricator.

@jcdhlzq
Copy link
Contributor Author

jcdhlzq commented Jun 5, 2023

Hi, what do you mean with "what is happening about this PR?" Are you seeing something unusual or is it just taking longer than usual to get reviewed?

It simplely means that there is no any information or any state change. So I cannot figure out if I should do something.

@cipolleschi
Copy link
Contributor

@jcdhlzq Ok, thanks. I'll try to push it forward!

Copy link
Member

@javache javache left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'd need these changes as well in the new architecture, ReactTextShadowNode is only used in the old architecture.

Comment on lines +203 to +206
TextView textView =
Assertions.assertNotNull(mInternalView, "mInternalView cannot be null");

return measureWithView(text, textView, width, widthMode, height, heightMode);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yoga measures on a background thread. It's unsafe to access TextView here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm sorry, could you offer some points exactly about the unsafe access? If it means some cases like #17530 , I think they are different. Because EditText has a background by default while TextView doesn't.

    <style name="Widget.EditText">
        <item name="focusable">true</item>
        <item name="focusableInTouchMode">true</item>
        <item name="clickable">true</item>
        <item name="background">?attr/editTextBackground</item>
        <item name="textAppearance">?attr/textAppearanceMediumInverse</item>
        <item name="textColor">?attr/editTextColor</item>
        <item name="gravity">center_vertical</item>
        <item name="breakStrategy">simple</item>
        <item name="hyphenationFrequency">@dimen/config_preferredHyphenationFrequency</item>
        <item name="defaultFocusHighlightEnabled">false</item>
    </style>
    <style name="Widget.TextView">
        <item name="textAppearance">?attr/textAppearanceSmall</item>
        <item name="textSelectHandleLeft">?attr/textSelectHandleLeft</item>
        <item name="textSelectHandleRight">?attr/textSelectHandleRight</item>
        <item name="textSelectHandle">?attr/textSelectHandle</item>
        <item name="textEditPasteWindowLayout">?attr/textEditPasteWindowLayout</item>
        <item name="textEditNoPasteWindowLayout">?attr/textEditNoPasteWindowLayout</item>
        <item name="textEditSidePasteWindowLayout">?attr/textEditSidePasteWindowLayout</item>
        <item name="textEditSideNoPasteWindowLayout">?attr/textEditSideNoPasteWindowLayout</item>
        <item name="textEditSuggestionItemLayout">?attr/textEditSuggestionItemLayout</item>
        <item name="textEditSuggestionContainerLayout">?attr/textEditSuggestionContainerLayout</item>
        <item name="textEditSuggestionHighlightStyle">?attr/textEditSuggestionHighlightStyle</item>
        <item name="textCursorDrawable">?attr/textCursorDrawable</item>
        <item name="breakStrategy">high_quality</item>
        <item name="hyphenationFrequency">@dimen/config_preferredHyphenationFrequency</item>
    </style>

Moreover, There are many cases where YogaMeasureFunction measures in the same way like ReactSwitch, ProgressBar.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the change is that with this PR, the ShadowNode now manages a new TextView on the background thread that is only used during layout?

So this is moving from laying out Spannable to laying out a background text element.

This is how TextInput works today on Paper, but Fabric, for both Text and TextInput, still measures off of the spannable/AttributedString.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the change is that with this PR, the ShadowNode now manages a new TextView on the background thread that is only used during layout?

So this is moving from laying out Spannable to laying out a background text element.

This is how TextInput works today on Paper, but Fabric, for both Text and TextInput, still measures off of the spannable/AttributedString.

That's right!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm seeing if we can dig up the context on why Fabric chose to avoid this style of measurement, but this is a pretty major change. Usually we'd want to A/B test something like this, but that isn't really a possibility because most of our internal apps do not run Paper-specific code. This also means we receive very limited test coverage, since this code is not exercised by tests against most of our own apps.

If it is possible to find the state we are missing in the layout, that would likely be more palatable. Do you know if this issue reproduces in Fabric?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@NickGerleman I'm also pretty concerned about memory here, as it means we now have two TextViews for every Text element on screen.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've had A/B test on various devices with different ROMs and put it on PRT environment and No any problem or bad case feedback reported.
As for Fabric mode, we don't use that architecture yet.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@NickGerleman I'm also pretty concerned about memory here, as it means we now have two TextViews for every Text element on screen.

Later, maybe after a few days, I'll have a test about peak memory difference and explain the root cause for this phenomenon which is related to Paint.nGetRunAdvance, a native method which may be modified by different ROM vendors. For recent days, I am too busy to take care about this PR in time. Sorry about that!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@NickGerleman I'm also pretty concerned about memory here, as it means we now have two TextViews for every Text element on screen.

The memory diff is about 1.2kb when measuring with TextView.
image

Copy link
Contributor Author

@jcdhlzq jcdhlzq Jul 3, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm seeing if we can dig up the context on why Fabric chose to avoid this style of measurement, but this is a pretty major change. Usually we'd want to A/B test something like this, but that isn't really a possibility because most of our internal apps do not run Paper-specific code. This also means we receive very limited test coverage, since this code is not exercised by tests against most of our own apps.

If it is possible to find the state we are missing in the layout, that would likely be more palatable. Do you know if this issue reproduces in Fabric?

@NickGerleman Yes, it reproduces when running on the app built with newArchEnabled=true.
image
image

@NickGerleman
Copy link
Contributor

@mdvacca got back to me offline with the history that we moved away from background component based measurement because of both performance and thread safety challenges.

So, I don’t think we’re going to be able to accept this solution.

@jcdhlzq
Copy link
Contributor Author

jcdhlzq commented Jul 4, 2023

@mdvacca got back to me offline with the history that we moved away from background component based measurement because of both performance and thread safety challenges.

So, I don’t think we’re going to be able to accept this solution.

Sorry, I don't get what the history is and could you offer some information about it ?

As for the performance and thread safety challeges you referred, there is no evidence in our prt environment over the past months.(For critical reasons, we have put it on prt env to make users have correct texts like $98, otherwise, users may have texts like $9)

Copy link

This PR is stale because it has been open 180 days with no activity. Remove stale label or comment or this will be closed in 7 days.

@github-actions github-actions bot added the Stale There has been a lack of activity on this issue and it may be closed soon. label Dec 31, 2023
Copy link

github-actions bot commented Jan 7, 2024

This PR was closed because it has been stalled for 7 days with no activity.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. Stale There has been a lack of activity on this issue and it may be closed soon.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants