From 1af2486f5d5cc7a5f20cef03067522485da43be3 Mon Sep 17 00:00:00 2001 From: lizhiqiang05 Date: Thu, 21 Sep 2023 19:46:05 +0800 Subject: [PATCH] fix: Text cut off issues when adjusting text size and font weight in system settings --- .../text/ReactTextAnchorViewManager.java | 10 +++ .../react/views/text/ReactTextView.java | 71 ++++++++++--------- 2 files changed, 48 insertions(+), 33 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextAnchorViewManager.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextAnchorViewManager.java index f683c24f74d760..679bcf47102bbf 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextAnchorViewManager.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextAnchorViewManager.java @@ -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); diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextView.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextView.java index 4af57295d9aac6..849f04661cf839 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextView.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextView.java @@ -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 @@ private void initView() { mEllipsizeLocation = TextUtils.TruncateAt.END; mSpanned = null; + mTextAttributes = new TextAttributes(); } /* package */ void recycleView() { @@ -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; } @@ -625,6 +607,8 @@ public void updateView() { ? null : mEllipsizeLocation; setEllipsize(ellipsizeLocation); + + applyTextAttributes(); } @Override @@ -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); } } }