mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
fix: Text cut off issues when adjusting text size and font weight in 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: https://github.com/facebook/react-native/pull/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
This commit is contained in:
committed by
Facebook GitHub Bot
parent
6118aff69d
commit
babbc3e43c
+10
@@ -75,6 +75,16 @@ public abstract class ReactTextAnchorViewManager<T extends View, C extends React
|
||||
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);
|
||||
|
||||
+39
-34
@@ -58,8 +58,6 @@ 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;
|
||||
@@ -67,6 +65,12 @@ public class ReactTextView extends AppCompatTextView implements ReactCompoundVie
|
||||
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);
|
||||
|
||||
@@ -98,6 +102,7 @@ public class ReactTextView extends AppCompatTextView implements ReactCompoundVie
|
||||
mEllipsizeLocation = TextUtils.TruncateAt.END;
|
||||
|
||||
mSpanned = null;
|
||||
mTextAttributes = new TextAttributes();
|
||||
}
|
||||
|
||||
/* package */ void recycleView() {
|
||||
@@ -587,29 +592,6 @@ public class ReactTextView extends AppCompatTextView implements ReactCompoundVie
|
||||
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;
|
||||
}
|
||||
@@ -625,6 +607,8 @@ public class ReactTextView extends AppCompatTextView implements ReactCompoundVie
|
||||
? null
|
||||
: mEllipsizeLocation;
|
||||
setEllipsize(ellipsizeLocation);
|
||||
|
||||
applyTextAttributes();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -680,16 +664,37 @@ public class ReactTextView extends AppCompatTextView implements ReactCompoundVie
|
||||
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);
|
||||
}
|
||||
|
||||
if (!Float.isNaN(mLetterSpacing)) {
|
||||
super.setLetterSpacing(mLetterSpacing);
|
||||
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());
|
||||
|
||||
float effectiveLetterSpacing = mTextAttributes.getEffectiveLetterSpacing();
|
||||
if (!Float.isNaN(effectiveLetterSpacing)) {
|
||||
super.setLetterSpacing(effectiveLetterSpacing);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user