Skip to content

Commit

Permalink
fix(android): font weight compatible with version 2.x (#3948)
Browse files Browse the repository at this point in the history
Co-authored-by: maxli <[email protected]>
  • Loading branch information
siguangli and siguangli2018 authored Jul 10, 2024
1 parent 5f40f8f commit d967cba
Show file tree
Hide file tree
Showing 6 changed files with 97 additions and 79 deletions.
2 changes: 1 addition & 1 deletion docs/api/style/appearance.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ const styles = StyleSheet.create({
fontSize: 14,
lineHeight: 18,
color: 'black',
fontWeight: 'normal'
},
buttonBar: {
flexDirection: 'row',
Expand All @@ -54,6 +55,7 @@ const styles = StyleSheet.create({
borderStyle: 'solid',
flexGrow: 1,
flexShrink: 1,
justifyContent: 'center',
},
buttonText: {
lineHeight: 24,
Expand All @@ -72,6 +74,7 @@ export default class TextExpo extends React.Component {
super(props);
this.state = {
fontSize: 16,
fontWeight: '400',
textShadowColor: 'grey',
textShadowOffset: {
x: 1,
Expand All @@ -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) {
Expand Down Expand Up @@ -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 => (
<View style={styles.itemTitle}>
Expand Down Expand Up @@ -194,6 +221,18 @@ export default class TextExpo extends React.Component {
<Text style={styles.buttonText}>缩小字体</Text>
</View>
</View>
{renderTitle('fontWeight')}
<View style={[styles.itemContent, { height: 125, color: 'blue', fontFamily: 'not-support-fontstyle' }]}>
<Text style={[styles.normalText, { fontWeight }]}>
{ `Text fontWeight is ${fontWeight}` }
</Text>
<View style={styles.button} onClick={this.incrementFontWeight}>
<Text style={styles.buttonText}>加粗字体</Text>
</View>
<View style={styles.button} onClick={this.decrementFontWeight}>
<Text style={styles.buttonText}>减细字体</Text>
</View>
</View>
{renderTitle('fontStyle')}
<View style={[styles.itemContent, { height: 100 }]}>
<Text style={[styles.normalText, { fontStyle: 'normal' }]}>Text fontStyle is normal</Text>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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<String, SparseArray<Typeface>> 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<Typeface> cache = sFontCache.get(fontFamilyName);
if (cache == null) {
cache = new SparseArray<>(4);
Expand All @@ -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);
}
Expand All @@ -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) {
Expand Down Expand Up @@ -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;
Expand All @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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();
}
}
Expand Down

0 comments on commit d967cba

Please sign in to comment.