From 1b00246c24821162018292c70120f519c6407825 Mon Sep 17 00:00:00 2001 From: maxli Date: Wed, 10 Jul 2024 11:57:35 +0800 Subject: [PATCH] fix(android): font weight compatible with version 2.x --- docs/api/style/appearance.md | 2 +- .../src/components/Text/index.jsx | 41 +++++++++- .../hippy/views/textinput/HippyTextInput.java | 21 +---- .../component/text/TextStyleSpan.java | 10 +-- .../renderer/component/text/TypeFaceUtil.java | 81 ++++++++++--------- .../renderer/node/TextVirtualNode.java | 21 +---- 6 files changed, 97 insertions(+), 79 deletions(-) diff --git a/docs/api/style/appearance.md b/docs/api/style/appearance.md index 4894ced4b9a..e96d56b7f03 100644 --- a/docs/api/style/appearance.md +++ b/docs/api/style/appearance.md @@ -174,7 +174,7 @@ | ------ | -------- | --- | | number \| string | 否 | Android、iOS -> Android API 28 以下仅支持 `normal`(`400`) 和 `bold`(`700`)两种字重,其它字重效果需配合 `fontFamily` 实现。 +> Android API 28 以下仅支持 `normal`和 `bold` 两种字重,其它字重效果需配合 `fontFamily` 实现,Android API 28 及以上可以支持设置`1` - `1000`的字重值。 # letterSpacing diff --git a/driver/js/examples/hippy-react-demo/src/components/Text/index.jsx b/driver/js/examples/hippy-react-demo/src/components/Text/index.jsx index 989240d6869..a9cddb230d8 100644 --- a/driver/js/examples/hippy-react-demo/src/components/Text/index.jsx +++ b/driver/js/examples/hippy-react-demo/src/components/Text/index.jsx @@ -41,6 +41,7 @@ const styles = StyleSheet.create({ fontSize: 14, lineHeight: 18, color: 'black', + fontWeight: 'normal' }, buttonBar: { flexDirection: 'row', @@ -54,6 +55,7 @@ const styles = StyleSheet.create({ borderStyle: 'solid', flexGrow: 1, flexShrink: 1, + justifyContent: 'center', }, buttonText: { lineHeight: 24, @@ -72,6 +74,7 @@ export default class TextExpo extends React.Component { super(props); this.state = { fontSize: 16, + fontWeight: '400', textShadowColor: 'grey', textShadowOffset: { x: 1, @@ -83,12 +86,36 @@ export default class TextExpo extends React.Component { }; this.incrementFontSize = this.incrementFontSize.bind(this); this.decrementFontSize = this.decrementFontSize.bind(this); + this.incrementFontWeight = this.incrementFontWeight.bind(this); + this.decrementFontWeight = this.decrementFontWeight.bind(this); this.incrementLine = this.incrementLine.bind(this); this.decrementLine = this.decrementLine.bind(this); this.changeMode = this.changeMode.bind(this); this.changeColor = this.changeColor.bind(this); } + incrementFontWeight() { + const { fontWeight } = this.state; + if (fontWeight == '1000') { + return; + } + var weightNumber = parseInt(fontWeight, 10); + weightNumber += 100; + this.setState({ + fontWeight: weightNumber.toString(), + }); + } + decrementFontWeight() { + const { fontWeight } = this.state; + if (fontWeight === '100') { + return; + } + var weightNumber = parseInt(fontWeight, 10); + weightNumber -= 100; + this.setState({ + fontWeight: weightNumber.toString(), + }); + } incrementFontSize() { const { fontSize } = this.state; if (fontSize === 24) { @@ -140,7 +167,7 @@ export default class TextExpo extends React.Component { } render() { - const { fontSize, textShadowColor, textShadowOffset, numberOfLines, ellipsizeMode, breakStrategy, + const { fontSize, fontWeight, textShadowColor, textShadowOffset, numberOfLines, ellipsizeMode, breakStrategy, scrollColor } = this.state; const renderTitle = title => ( @@ -194,6 +221,18 @@ export default class TextExpo extends React.Component { 缩小字体 + {renderTitle('fontWeight')} + + + { `Text fontWeight is ${fontWeight}` } + + + 加粗字体 + + + 减细字体 + + {renderTitle('fontStyle')} Text fontStyle is normal diff --git a/renderer/native/android/src/main/java/com/tencent/mtt/hippy/views/textinput/HippyTextInput.java b/renderer/native/android/src/main/java/com/tencent/mtt/hippy/views/textinput/HippyTextInput.java index 26219b4e1d5..231aefda270 100644 --- a/renderer/native/android/src/main/java/com/tencent/mtt/hippy/views/textinput/HippyTextInput.java +++ b/renderer/native/android/src/main/java/com/tencent/mtt/hippy/views/textinput/HippyTextInput.java @@ -90,7 +90,7 @@ public class HippyTextInput extends AppCompatEditText implements HippyViewBase, private int mListenerFlag = 0; private ReactContentSizeWatcher mReactContentSizeWatcher = null; private boolean mItalic = false; - private int mFontWeight = TypeFaceUtil.WEIGHT_NORMAL; + private String mFontWeight = TypeFaceUtil.TEXT_FONT_STYLE_NORMAL; private float mLineSpacingMultiplier = 1.0f; private float mLineSpacingExtra = 0.0f; private int mLineHeight = 0; @@ -763,23 +763,8 @@ public void setFontFamily(String family) { } public void setFontWeight(String weight) { - int fontWeight; - if (TextUtils.isEmpty(weight) || TypeFaceUtil.TEXT_FONT_STYLE_NORMAL.equals(weight)) { - // case normal - fontWeight = TypeFaceUtil.WEIGHT_NORMAL; - } else if (TypeFaceUtil.TEXT_FONT_STYLE_BOLD.equals(weight)) { - // case bold - fontWeight = TypeFaceUtil.WEIGHT_BOLE; - } else { - // case number - try { - fontWeight = Math.min(Math.max(1, Integer.parseInt(weight)), 1000); - } catch (NumberFormatException ignored) { - fontWeight = TypeFaceUtil.WEIGHT_NORMAL; - } - } - if (fontWeight != mFontWeight) { - mFontWeight = fontWeight; + if (!mFontWeight.equals(weight)) { + mFontWeight = weight; mShouldUpdateTypeface = true; } } diff --git a/renderer/native/android/src/main/java/com/tencent/renderer/component/text/TextStyleSpan.java b/renderer/native/android/src/main/java/com/tencent/renderer/component/text/TextStyleSpan.java index f02c7d1e191..f6d1e449904 100644 --- a/renderer/native/android/src/main/java/com/tencent/renderer/component/text/TextStyleSpan.java +++ b/renderer/native/android/src/main/java/com/tencent/renderer/component/text/TextStyleSpan.java @@ -22,25 +22,25 @@ public class TextStyleSpan extends MetricAffectingSpan { private final boolean mItalic; - private final int mWeight; + private final String mFontWeight; private final String mFontFamily; private final FontAdapter mFontAdapter; - public TextStyleSpan(boolean italic, int fontWeight, String fontFamily, + public TextStyleSpan(boolean italic, String fontWeight, String fontFamily, FontAdapter adapter) { mItalic = italic; - mWeight = fontWeight; + mFontWeight = fontWeight; mFontFamily = fontFamily; mFontAdapter = adapter; } @Override public void updateDrawState(TextPaint textPaint) { - TypeFaceUtil.apply(textPaint, mItalic, mWeight, mFontFamily, mFontAdapter); + TypeFaceUtil.apply(textPaint, mItalic, mFontWeight, mFontFamily, mFontAdapter); } @Override public void updateMeasureState(TextPaint textPaint) { - TypeFaceUtil.apply(textPaint, mItalic, mWeight, mFontFamily, mFontAdapter); + TypeFaceUtil.apply(textPaint, mItalic, mFontWeight, mFontFamily, mFontAdapter); } } diff --git a/renderer/native/android/src/main/java/com/tencent/renderer/component/text/TypeFaceUtil.java b/renderer/native/android/src/main/java/com/tencent/renderer/component/text/TypeFaceUtil.java index ce7d5a415fe..3dd6043f22b 100644 --- a/renderer/native/android/src/main/java/com/tencent/renderer/component/text/TypeFaceUtil.java +++ b/renderer/native/android/src/main/java/com/tencent/renderer/component/text/TypeFaceUtil.java @@ -18,11 +18,11 @@ import android.graphics.Paint; import android.graphics.Typeface; -import android.os.Build; +import android.os.Build.VERSION; +import android.os.Build.VERSION_CODES; import android.text.TextUtils; import android.util.SparseArray; -import androidx.annotation.ChecksSdkIntAtLeast; import androidx.annotation.Nullable; import com.tencent.mtt.hippy.utils.ContextHolder; @@ -43,26 +43,25 @@ public class TypeFaceUtil { private static final String[] FONT_EXTENSIONS = {".ttf", ".otf"}; private static final String FONTS_PATH = "fonts/"; private static final Map> sFontCache = new HashMap<>(); - @ChecksSdkIntAtLeast(api = Build.VERSION_CODES.P) - private static final boolean SUPPORT_FONT_WEIGHT = Build.VERSION.SDK_INT >= Build.VERSION_CODES.P; /** - * @deprecated use {@link #getTypeface(String, int, boolean, FontAdapter)} instead + * @deprecated use {@link #getTypeface(String, String, boolean, FontAdapter)} instead */ @Deprecated public static Typeface getTypeface(String fontFamilyName, int style, @Nullable FontAdapter fontAdapter) { boolean italic = (style & Typeface.ITALIC) != 0; - int weightNumber = (style & Typeface.BOLD) != 0 ? WEIGHT_BOLE : WEIGHT_NORMAL; - return getTypeface(fontFamilyName, weightNumber, italic, fontAdapter); + String weight = (style & Typeface.BOLD) != 0 ? TEXT_FONT_STYLE_BOLD : TEXT_FONT_STYLE_NORMAL; + return getTypeface(fontFamilyName, weight, italic, fontAdapter); } - public static Typeface getTypeface(String fontFamilyName, int weight, boolean italic, + public static Typeface getTypeface(String fontFamilyName, String weight, boolean italic, @Nullable FontAdapter fontAdapter) { - final int style = toStyle(weight, italic); + int weightNumber = getWeightNumber(weight); + final int style = toStyle(weight, weightNumber, italic); Typeface typeface = (fontAdapter != null) ? fontAdapter.getCustomTypeface(fontFamilyName, style) : null; if (typeface == null) { - final int key = SUPPORT_FONT_WEIGHT ? ((weight << 1) | (italic ? 1 : 0)) : style; + final int key = (weightNumber > 0) ? ((weightNumber << 1) | (italic ? 1 : 0)) : style; SparseArray cache = sFontCache.get(fontFamilyName); if (cache == null) { cache = new SparseArray<>(4); @@ -71,7 +70,7 @@ public static Typeface getTypeface(String fontFamilyName, int weight, boolean it typeface = cache.get(key); } if (typeface == null) { - typeface = createTypeface(fontFamilyName, weight, italic, fontAdapter); + typeface = createTypeface(fontFamilyName, weightNumber, style, italic, fontAdapter); if (typeface != null) { cache.put(key, typeface); } @@ -80,9 +79,8 @@ public static Typeface getTypeface(String fontFamilyName, int weight, boolean it return typeface; } - private static Typeface createTypeface(String fontFamilyName, int weight, boolean italic, + private static Typeface createTypeface(String fontFamilyName, int weightNumber, int style, boolean italic, @Nullable FontAdapter fontAdapter) { - final int style = toStyle(weight, italic); final String extension = EXTENSIONS[style]; final String[] familyNameList; if (fontFamilyName.indexOf(',') == -1) { @@ -113,8 +111,8 @@ private static Typeface createTypeface(String fontFamilyName, int weight, boolea try { Typeface typeface = Typeface.createFromAsset(ContextHolder.getAppContext().getAssets(), fileName); if (typeface != null && !typeface.equals(Typeface.DEFAULT)) { - if (SUPPORT_FONT_WEIGHT) { - return Typeface.create(typeface, weight, italic); + if (VERSION.SDK_INT >= VERSION_CODES.P && weightNumber > 0) { + return Typeface.create(typeface, weightNumber, italic); } // "bold" has no effect on api level < P, prefer to use `Paint.setFakeBoldText(boolean)` return italic ? Typeface.create(typeface, Typeface.ITALIC) : typeface; @@ -138,46 +136,57 @@ private static Typeface createTypeface(String fontFamilyName, int weight, boolea } } } - final Typeface systemDefault = Typeface.create(Typeface.DEFAULT, style); for (String splitName : familyNameList) { Typeface typeface = Typeface.create(splitName, style); if (typeface != null && !typeface.equals(systemDefault)) { - return SUPPORT_FONT_WEIGHT ? Typeface.create(typeface, weight, italic) : typeface; + if (VERSION.SDK_INT >= VERSION_CODES.P && weightNumber > 0) { + return Typeface.create(typeface, weightNumber, italic); + } + return typeface; } } - return SUPPORT_FONT_WEIGHT ? Typeface.create(systemDefault, weight, italic) : systemDefault; + return (VERSION.SDK_INT >= VERSION_CODES.P && weightNumber > 0) ? + Typeface.create(systemDefault, weightNumber, italic) : systemDefault; } - private static int toStyle(int weight, boolean italic) { - return weight < WEIGHT_BOLE ? - (italic ? Typeface.ITALIC : Typeface.NORMAL) : - (italic ? Typeface.BOLD_ITALIC : Typeface.BOLD); + private static int getWeightNumber(String weight) { + int weightNumber = 0; + try { + weightNumber = Math.min(Math.max(1, Integer.parseInt(weight)), 1000); + } catch (NumberFormatException ignored) { + // Weight supports setting non numeric strings + } + return weightNumber; } - /** - * @deprecated use {@link #apply(Paint, boolean, int, String, FontAdapter)} instead - */ - @Deprecated - public static void apply(Paint paint, int style, int weight, String family, - @Nullable FontAdapter fontAdapter) { - boolean italic = style == Typeface.ITALIC; - int weightNumber = weight == Typeface.BOLD ? WEIGHT_BOLE : WEIGHT_NORMAL; - apply(paint, italic, weightNumber, family, fontAdapter); + private static int toStyle(String weight, int weightNumber, boolean italic) { + if (weight.equals(TEXT_FONT_STYLE_NORMAL)) { + return italic ? Typeface.ITALIC : Typeface.NORMAL; + } else if (weight.equals(TEXT_FONT_STYLE_BOLD)) { + return italic ? Typeface.BOLD_ITALIC : Typeface.BOLD; + } else { + return weightNumber < WEIGHT_BOLE ? + (italic ? Typeface.ITALIC : Typeface.NORMAL) : + (italic ? Typeface.BOLD_ITALIC : Typeface.BOLD); + } } - public static void apply(Paint paint, boolean italic, int weight, String familyName, + public static void apply(Paint paint, boolean italic, String weight, String familyName, @Nullable FontAdapter fontAdapter) { Typeface typeface; + int weightNumber = getWeightNumber(weight); if (TextUtils.isEmpty(familyName)) { final Typeface base = paint.getTypeface(); - typeface = SUPPORT_FONT_WEIGHT - ? Typeface.create(base, weight, italic) - : Typeface.create(base, toStyle(weight, italic)); + if (VERSION.SDK_INT >= VERSION_CODES.P && weightNumber > 0) { + typeface = Typeface.create(base, weightNumber, italic); + } else { + typeface = Typeface.create(base, toStyle(weight, weightNumber, italic)); + } } else { typeface = getTypeface(familyName, weight, italic, fontAdapter); } - if (weight >= WEIGHT_BOLE && typeface != null && !typeface.isBold()) { + if (weightNumber >= WEIGHT_BOLE && typeface != null && !typeface.isBold()) { paint.setFakeBoldText(true); } paint.setTypeface(typeface); diff --git a/renderer/native/android/src/main/java/com/tencent/renderer/node/TextVirtualNode.java b/renderer/native/android/src/main/java/com/tencent/renderer/node/TextVirtualNode.java index 986e9ff64e1..238d78f6955 100644 --- a/renderer/native/android/src/main/java/com/tencent/renderer/node/TextVirtualNode.java +++ b/renderer/native/android/src/main/java/com/tencent/renderer/node/TextVirtualNode.java @@ -88,7 +88,7 @@ public class TextVirtualNode extends VirtualNode { protected int mColor = Color.BLACK; protected int mNumberOfLines; protected boolean mItalic = false; - protected int mFontWeight = TypeFaceUtil.WEIGHT_NORMAL; + protected String mFontWeight = TypeFaceUtil.TEXT_FONT_STYLE_NORMAL; protected int mFontSize = (int) Math.ceil(PixelUtil.dp2px(NodeProps.FONT_SIZE_SP)); protected int mShadowColor = TEXT_SHADOW_COLOR_DEFAULT; protected float mShadowOffsetDx = 0.0f; @@ -183,23 +183,8 @@ public void setFontFamily(String family) { @SuppressWarnings("unused") @HippyControllerProps(name = NodeProps.FONT_WEIGHT, defaultType = HippyControllerProps.STRING) public void setFontWeight(String weight) { - int fontWeight; - if (TextUtils.isEmpty(weight) || TypeFaceUtil.TEXT_FONT_STYLE_NORMAL.equals(weight)) { - // case normal - fontWeight = TypeFaceUtil.WEIGHT_NORMAL; - } else if (TypeFaceUtil.TEXT_FONT_STYLE_BOLD.equals(weight)) { - // case bold - fontWeight = TypeFaceUtil.WEIGHT_BOLE; - } else { - // case number - try { - fontWeight = Math.min(Math.max(1, Integer.parseInt(weight)), 1000); - } catch (NumberFormatException ignored) { - fontWeight = TypeFaceUtil.WEIGHT_NORMAL; - } - } - if (fontWeight != mFontWeight) { - mFontWeight = fontWeight; + if (!mFontWeight.equals(weight)) { + mFontWeight = weight; markDirty(); } }