Skip to content

Commit

Permalink
fix: Text cut off issues when adjusting text size and font weight in …
Browse files Browse the repository at this point in the history
…system settings (#39581)

Summary:
Fix Text cut off issues when adjusting text size and font weight in system settings.

This pr fixed the problem that can be reproduced with the [snack](https://snack.expo.dev/fl5DSrLBJ) on Xiaomi devices with MIUI13 and MIUI14. The problem is shown as the image below: the number "999" is cut off and only "99" is rendered.
<img src="https://github.com/facebook/react-native/assets/23273745/64269ced-4060-4ab5-8233-8199e4f2acbd" width="20%" height="20%" alt="text-cutoff-when-scaling-miui14" />

The problem is produced with setting font scaling in system settings like the image below shows.

<img src="https://github.com/facebook/react-native/assets/23273745/c31d1bf2-d038-4536-b1a4-509050f2aa7c" width="20%" height="20%" alt="settings" />

This text cut off case can be avoided by setting [`allowFontScaling`](https://reactnative.cn/docs/text#allowfontscaling) to false. But this pr can make it no matter what value `allowFontScaling` is set.

The root cause of this case, according to MIUI developers, is that Misans typeface, as a variable font which will adjust the weight of different font axes with different font size, gets different widths when Text is measured and drawn for a bug in the framework of MIUI rom. They will fix this bug in next version while this pr fixed it in old versions.

## Changelog:

[ANDROID][FIXED]-Fix Text cut off issues when adjusting text size and font weight in system settings.

<!-- Help reviewers and the release process by writing your own changelog entry.

Pick one each for the category and type tags:

[ANDROID|GENERAL|IOS|INTERNAL] [BREAKING|ADDED|CHANGED|DEPRECATED|REMOVED|FIXED|SECURITY] - Message

For more details, see:
https://reactnative.dev/contributing/changelogs-in-pull-requests

Pull Request resolved: #39581

Test Plan:
The effect after fixed is shown in the image below.

<img src="https://github.com/facebook/react-native/assets/23273745/1f93f47f-5cdf-4ee1-934a-6cb3b04309ea" width="20%" height="20%" alt="fixed" />

Reviewed By: NickGerleman

Differential Revision: D49509633

Pulled By: ryancat

fbshipit-source-id: fd93f14bdbced8026a45dc9e0299465962433de5
  • Loading branch information
lizhiqiang05 authored and facebook-github-bot committed Sep 26, 2023
1 parent 6118aff commit babbc3e
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,16 @@ public void setAdjustFontSizeToFit(ReactTextView view, boolean adjustsFontSizeTo
view.setAdjustFontSizeToFit(adjustsFontSizeToFit);
}

@ReactProp(name = ViewProps.ALLOW_FONT_SCALING, defaultBoolean = true)
public void setAllowFontScaling(ReactTextView view, boolean allowFontScaling) {
view.setAllowFontScaling(allowFontScaling);
}

@ReactProp(name = ViewProps.MAX_FONT_SIZE_MULTIPLIER, defaultFloat = Float.NaN)
public void setMaxFontSizeMultiplier(ReactTextView view, float maxFontSizeMultiplier) {
view.setMaxFontSizeMultiplier(maxFontSizeMultiplier);
}

@ReactProp(name = ViewProps.FONT_SIZE)
public void setFontSize(ReactTextView view, float fontSize) {
view.setFontSize(fontSize);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,15 +58,19 @@ public class ReactTextView extends AppCompatTextView implements ReactCompoundVie
private int mNumberOfLines;
private TextUtils.TruncateAt mEllipsizeLocation;
private boolean mAdjustsFontSizeToFit;
private float mFontSize = Float.NaN;
private float mLetterSpacing = Float.NaN;
private int mLinkifyMaskType;
private boolean mNotifyOnInlineViewLayout;
private boolean mTextIsSelectable;

private ReactViewBackgroundManager mReactBackgroundManager;
private Spannable mSpanned;

/**
* Used to collect some text size affecting attributes to fix some text cut-off issues when users
* adjust text size and font weight to the max value in system font settings.
*/
private TextAttributes mTextAttributes;

public ReactTextView(Context context) {
super(context);

Expand Down Expand Up @@ -98,6 +102,7 @@ private void initView() {
mEllipsizeLocation = TextUtils.TruncateAt.END;

mSpanned = null;
mTextAttributes = new TextAttributes();
}

/* package */ void recycleView() {
Expand Down Expand Up @@ -587,29 +592,6 @@ public void setAdjustFontSizeToFit(boolean adjustsFontSizeToFit) {
mAdjustsFontSizeToFit = adjustsFontSizeToFit;
}

public void setFontSize(float fontSize) {
mFontSize =
mAdjustsFontSizeToFit
? (float) Math.ceil(PixelUtil.toPixelFromSP(fontSize))
: (float) Math.ceil(PixelUtil.toPixelFromDIP(fontSize));

applyTextAttributes();
}

public void setLetterSpacing(float letterSpacing) {
if (Float.isNaN(letterSpacing)) {
return;
}

float letterSpacingPixels = PixelUtil.toPixelFromDIP(letterSpacing);

// `letterSpacingPixels` and `getEffectiveFontSize` are both in pixels,
// yielding an accurate em value.
mLetterSpacing = letterSpacingPixels / mFontSize;

applyTextAttributes();
}

public void setEllipsizeLocation(TextUtils.TruncateAt ellipsizeLocation) {
mEllipsizeLocation = ellipsizeLocation;
}
Expand All @@ -625,6 +607,8 @@ public void updateView() {
? null
: mEllipsizeLocation;
setEllipsize(ellipsizeLocation);

applyTextAttributes();
}

@Override
Expand Down Expand Up @@ -680,16 +664,37 @@ protected boolean dispatchHoverEvent(MotionEvent event) {
return super.dispatchHoverEvent(event);
}

private void applyTextAttributes() {
// Workaround for an issue where text can be cut off with an ellipsis when
// using certain font sizes and padding. Sets the provided text size and
// letter spacing to ensure consistent rendering and prevent cut-off.
if (!Float.isNaN(mFontSize)) {
setTextSize(TypedValue.COMPLEX_UNIT_PX, mFontSize);
public void setLetterSpacing(float letterSpacing) {
mTextAttributes.setLetterSpacing(letterSpacing);
}

public void setAllowFontScaling(boolean allowFontScaling) {
if (mTextAttributes.getAllowFontScaling() != allowFontScaling) {
mTextAttributes.setAllowFontScaling(allowFontScaling);
}
}

public void setFontSize(float fontSize) {
mTextAttributes.setFontSize(fontSize);
}

public void setMaxFontSizeMultiplier(float maxFontSizeMultiplier) {
if (maxFontSizeMultiplier != mTextAttributes.getMaxFontSizeMultiplier()) {
mTextAttributes.setMaxFontSizeMultiplier(maxFontSizeMultiplier);
}
}

private void applyTextAttributes() {
// In general, the `getEffective*` functions return `Float.NaN` if the
// property hasn't been set.

// `getEffectiveFontSize` always returns a value so don't need to check for anything like
// `Float.NaN`.
setTextSize(TypedValue.COMPLEX_UNIT_PX, mTextAttributes.getEffectiveFontSize());

if (!Float.isNaN(mLetterSpacing)) {
super.setLetterSpacing(mLetterSpacing);
float effectiveLetterSpacing = mTextAttributes.getEffectiveLetterSpacing();
if (!Float.isNaN(effectiveLetterSpacing)) {
super.setLetterSpacing(effectiveLetterSpacing);
}
}
}

0 comments on commit babbc3e

Please sign in to comment.