最近在使用custom fontFamily的时候遇到一个小坑.
正常的使用方法可以参照这里:https://github.com/refinery29/react-native-cheat-sheet.
但是我在使用某个custom fontFamily的时候,发现无论如何都不能正确取到这个font, 而其他的custom fontFamily则是可以的. 于是进去看源码.
在RCTConvert.m
中,
+ (UIFont *)UIFont:(UIFont *)font withFamily:(id)family
size:(id)size weight:(id)weight style:(id)style
scaleMultiplier:(CGFloat)scaleMultiplier
最下边有段这样的代码:
UIFont *bestMatch = font;
CGFloat closestWeight = INFINITY;
for (NSString *name in [UIFont fontNamesForFamilyName:familyName]) {
UIFont *match = [UIFont fontWithName:name size:fontSize];
if (isItalic == RCTFontIsItalic(match) &&
isCondensed == RCTFontIsCondensed(match)) {
CGFloat testWeight = RCTWeightOfFont(match);
if (ABS(testWeight - fontWeight) < ABS(closestWeight - fontWeight)) {
bestMatch = match;
closestWeight = testWeight;
}
}
}
return bestMatch;
我发现我在使用名为'Impat'的自定义字体时,
isItalic == RCTFontIsItalic(match) &&
isCondensed == RCTFontIsCondensed(match)
return false
所以 bestMatch
return nil
.
最终导致我无法正确取到这个font.
我不明白为什么React Native的作者们, 要在这里判断一定是isItalic
isCondensed
才有对应的逻辑, 如果不是, 就返回nil了.
暂时的处理是:
// Get the closest font that matches the given weight for the fontFamily
UIFont *bestMatch = font;
CGFloat closestWeight = INFINITY;
for (NSString *name in [UIFont fontNamesForFamilyName:familyName]) {
UIFont *match = [UIFont fontWithName:name size:fontSize];
if (isItalic == RCTFontIsItalic(match) &&
isCondensed == RCTFontIsCondensed(match)) {
CGFloat testWeight = RCTWeightOfFont(match);
if (ABS(testWeight - fontWeight) < ABS(closestWeight - fontWeight)) {
bestMatch = match;
closestWeight = testWeight;
}
else { // else是我加的
bestMatch = match;
}
}
else { // else是我加的. 使用"Impact"字体时,并没有走这个对应的if.导致bestMatch为nil
bestMatch = match;
}
}
return bestMatch;
在一个类似的issue下提了: https://github.com/facebook/react-native/issues/6046#issuecomment-214984034
暂时记录一下, 等有时间仔细看看这里.