是否可以在 React Native 中使用 iOS 13 种系统字体?
Is it possible to use iOS 13 system fonts in React Native?
我想在我的 React Native 应用程序中使用自 iOS 13 以来可用的新系统字体。特别是,我需要 rounded、serif 和 monospaced。在本机方面,它是使用 UIFontDescriptor.SystemDesign
https://developer.apple.com/videos/play/wwdc2019/227/?time=142
完成的
在 React Native 方面,我们可以将 { fontFamily: 'System' }
与 StyleSheet
结合使用,但它仅提供默认的无衬线设计。
是否可以使用一些 Swift 代码来修改文本组件的字体描述符?或者我应该在 React Native 存储库中提出一个问题并提出功能请求吗?
您不能在 React Native 中指定系统字体的字体变体。您可以下载并使用该字体作为自定义字体。 [1]
我建议从 utils/primitives 文件中导出组件并设置该组件的样式以使用自定义字体。
// Text.js
import {Text} from 'react-native'
export const Text = () => <Text style={{fontFamily: 'customFontFamily'}} />;
// App.js
import {View} from 'react-native'
import {Text} from './Text'
const App = () => {
return (
<View>
<Text>Hello World</Text>
</View>
)
}'
export default App;
[1] https://gist.github.com/parshap/cf9cf0388d55a044004e5e78fa317b39
React Native 不使用 UIFontDescriptor
和 iOS 上的指定设计,但您可以使用下一个运行时黑客技术 - “Method Swizzling”来拦截对 UIFont
的系统调用和 return 一个需要的但它应该在 ObjC 中实现。
只需将此 ObjC 代码添加到您的 XCode 项目中:
// UIFont+SystemDesign.m
#import <objc/runtime.h>
@implementation UIFont (SystemDesign)
+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Class class = object_getClass((id)self);
SEL originalSelector = @selector(fontWithName:size:);
Method originalMethod = class_getClassMethod(class, originalSelector);
SEL swizzledSelector = @selector(_fontWithName:size:);
Method swizzledMethod = class_getClassMethod(class, swizzledSelector);
BOOL didAddMethod = class_addMethod(class, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod));
if (didAddMethod) {
class_replaceMethod(class, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
}
else {
method_exchangeImplementations(originalMethod, swizzledMethod);
}
});
}
#pragma mark - Method Swizzling
+ (UIFont *)_fontWithName:(NSString *)fontName size:(CGFloat)fontSize {
NSString* const systemRounded = @"System-Rounded";
NSString* const systemSerif = @"System-Serif";
NSString* const systemMonospaced = @"System-Monospaced";
NSArray* fonts = @[systemRounded, systemSerif, systemMonospaced];
if ([fonts containsObject:fontName]) {
if (@available(iOS 13.0, *)) {
NSDictionary* designs = @{systemRounded : UIFontDescriptorSystemDesignRounded,
systemSerif : UIFontDescriptorSystemDesignSerif,
systemMonospaced : UIFontDescriptorSystemDesignMonospaced};
UIFontDescriptor *fontDescriptor = [UIFont systemFontOfSize:fontSize].fontDescriptor;
fontDescriptor = [fontDescriptor fontDescriptorWithDesign: designs[fontName]];
return [UIFont fontWithDescriptor:fontDescriptor size:fontSize];
}
else {
return [UIFont systemFontOfSize:fontSize];
}
}
return [self _fontWithName:fontName size:fontSize];
}
@end
然后您可以在 React Native 文件中使用 'System-Rounded'、'System-Serif' 和 'System-Monospaced' 字体:
export default function App() {
return (
<View style={styles.container}>
<Text style={styles.systemDefault}>Default</Text>
<Text style={styles.systemRounded}>Rounded</Text>
<Text style={styles.systemSerif}>Serif</Text>
<Text style={styles.systemMonospaced}>Monospaced</Text>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
systemDefault: {
fontFamily: 'System',
fontSize: 20,
},
systemRounded: {
fontFamily: 'System-Rounded',
fontSize: 20,
},
systemSerif: {
fontFamily: 'System-Serif',
fontSize: 20,
},
systemMonospaced: {
fontFamily: 'System-Monospaced',
fontSize: 20,
},
});
我想在我的 React Native 应用程序中使用自 iOS 13 以来可用的新系统字体。特别是,我需要 rounded、serif 和 monospaced。在本机方面,它是使用 UIFontDescriptor.SystemDesign
https://developer.apple.com/videos/play/wwdc2019/227/?time=142
在 React Native 方面,我们可以将 { fontFamily: 'System' }
与 StyleSheet
结合使用,但它仅提供默认的无衬线设计。
是否可以使用一些 Swift 代码来修改文本组件的字体描述符?或者我应该在 React Native 存储库中提出一个问题并提出功能请求吗?
您不能在 React Native 中指定系统字体的字体变体。您可以下载并使用该字体作为自定义字体。 [1]
我建议从 utils/primitives 文件中导出组件并设置该组件的样式以使用自定义字体。
// Text.js
import {Text} from 'react-native'
export const Text = () => <Text style={{fontFamily: 'customFontFamily'}} />;
// App.js
import {View} from 'react-native'
import {Text} from './Text'
const App = () => {
return (
<View>
<Text>Hello World</Text>
</View>
)
}'
export default App;
[1] https://gist.github.com/parshap/cf9cf0388d55a044004e5e78fa317b39
React Native 不使用 UIFontDescriptor
和 iOS 上的指定设计,但您可以使用下一个运行时黑客技术 - “Method Swizzling”来拦截对 UIFont
的系统调用和 return 一个需要的但它应该在 ObjC 中实现。
只需将此 ObjC 代码添加到您的 XCode 项目中:
// UIFont+SystemDesign.m
#import <objc/runtime.h>
@implementation UIFont (SystemDesign)
+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Class class = object_getClass((id)self);
SEL originalSelector = @selector(fontWithName:size:);
Method originalMethod = class_getClassMethod(class, originalSelector);
SEL swizzledSelector = @selector(_fontWithName:size:);
Method swizzledMethod = class_getClassMethod(class, swizzledSelector);
BOOL didAddMethod = class_addMethod(class, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod));
if (didAddMethod) {
class_replaceMethod(class, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
}
else {
method_exchangeImplementations(originalMethod, swizzledMethod);
}
});
}
#pragma mark - Method Swizzling
+ (UIFont *)_fontWithName:(NSString *)fontName size:(CGFloat)fontSize {
NSString* const systemRounded = @"System-Rounded";
NSString* const systemSerif = @"System-Serif";
NSString* const systemMonospaced = @"System-Monospaced";
NSArray* fonts = @[systemRounded, systemSerif, systemMonospaced];
if ([fonts containsObject:fontName]) {
if (@available(iOS 13.0, *)) {
NSDictionary* designs = @{systemRounded : UIFontDescriptorSystemDesignRounded,
systemSerif : UIFontDescriptorSystemDesignSerif,
systemMonospaced : UIFontDescriptorSystemDesignMonospaced};
UIFontDescriptor *fontDescriptor = [UIFont systemFontOfSize:fontSize].fontDescriptor;
fontDescriptor = [fontDescriptor fontDescriptorWithDesign: designs[fontName]];
return [UIFont fontWithDescriptor:fontDescriptor size:fontSize];
}
else {
return [UIFont systemFontOfSize:fontSize];
}
}
return [self _fontWithName:fontName size:fontSize];
}
@end
然后您可以在 React Native 文件中使用 'System-Rounded'、'System-Serif' 和 'System-Monospaced' 字体:
export default function App() {
return (
<View style={styles.container}>
<Text style={styles.systemDefault}>Default</Text>
<Text style={styles.systemRounded}>Rounded</Text>
<Text style={styles.systemSerif}>Serif</Text>
<Text style={styles.systemMonospaced}>Monospaced</Text>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
systemDefault: {
fontFamily: 'System',
fontSize: 20,
},
systemRounded: {
fontFamily: 'System-Rounded',
fontSize: 20,
},
systemSerif: {
fontFamily: 'System-Serif',
fontSize: 20,
},
systemMonospaced: {
fontFamily: 'System-Monospaced',
fontSize: 20,
},
});