React Native Android自定义字体无法通过fontWeight控制字重
问题描述
已将下列Poppins字体文件放入项目android/src/main/assets目录:
Poppins-Bold.ttf Poppins-Regular.ttf Poppins-Light.ttf Poppins-Medium.ttf Poppins-MediumItalic.ttf
编写如下样式配置时,iOS端可正常加载对应字重字体,但Android端字体不生效:
header: { fontFamily: 'Poppins', fontWeight: '700' }
如果直接指定fontFamily: 'Poppins-Bold',双端均可正常加载字体,但无法通过fontWeight属性灵活切换字重,需要可兼容双端、支持通过fontWeight配置字重的落地方案。
可行方案
方案1:自动链接生成字体映射(推荐,开发成本最低)
Android系统本身不会像iOS一样自动根据字体族名+字重模糊匹配assets目录下的字体文件,只要提前做好字体族和字重的映射配置,就能和iOS保持一致的写法。
- 先把所有字体文件统一放到项目内的固定目录,比如
./src/assets/fonts/,保证Android assets目录、iOS项目引入的字体和这个目录下的文件完全一致 - 在项目根目录新建
react-native.config.js配置文件,添加如下内容:
module.exports = { project: { ios: {}, android: {}, }, assets: ['./src/assets/fonts/'], };
- 项目根目录执行
npx react-native-asset命令,工具会自动完成双端字体链接:iOS端会把字体加入项目资源,Android端会自动生成字体族XML配置,把不同字重、斜体样式和对应的ttf文件做绑定 - 配置完成后直接使用和iOS一致的写法即可,系统会自动根据
fontWeight、fontStyle匹配对应字体文件,匹配规则如下:fontWeight: '300'自动匹配 Poppins-Light.ttffontWeight: '400'自动匹配 Poppins-Regular.ttffontWeight: '500'自动匹配 Poppins-Medium.ttffontWeight: '700'自动匹配 Poppins-Bold.ttffontWeight: '500' + fontStyle: 'italic'自动匹配 Poppins-MediumItalic.ttf
// 双端通用写法,不需要手动拼字体文件名 header: { fontFamily: 'Poppins', fontWeight: '700' }
如果执行完命令后Android端仍不生效,进入android目录执行./gradlew clean清理构建缓存后重新打包即可。
方案2:封装字体样式工具函数(无配置依赖,可控性强)
如果不想改动项目构建配置,可以在逻辑层做双端适配封装,Android端根据传入的字重、样式参数自动拼接对应字体文件名,iOS端保持原有逻辑:
import { Platform, StyleSheet } from 'react-native'; const fontConfig = { family: 'Poppins', weightMap: { 300: 'Light', 400: 'Regular', 500: 'Medium', 700: 'Bold' } } /** * 生成跨端兼容的字体样式 * @param {number} weight 字重值 * @param {boolean} italic 是否斜体 * @returns 字体样式对象 */ export const getFont = (weight = 400, italic = false) => { if (Platform.OS === 'ios') { return { fontFamily: fontConfig.family, fontWeight: String(weight), fontStyle: italic ? 'italic' : 'normal' } } const weightSuffix = fontConfig.weightMap[weight] || 'Regular'; const italicSuffix = italic ? 'Italic' : ''; return { fontFamily: `${fontConfig.family}-${weightSuffix}${italicSuffix}` } } // 使用示例 const styles = StyleSheet.create({ header: { ...getFont(700), fontSize: 20, color: '#1a1a1a' } })
方案3:合并为单可变字体文件(不推荐)
可以使用专业字体编辑工具将多个不同字重的ttf文件合并为单个可变字体文件,合并后单文件内置所有字重信息,理论上可支持直接通过fontWeight切换字重,但存在两个明显问题:
- 字体合并操作流程繁琐,很容易出现字形丢失、字体损坏的问题
- Android 8.0以下版本对可变字体的兼容性极差,容易出现渲染错位、字体不生效的问题
除非项目有强制单字体文件的需求,否则不建议采用该方案。
内容的提问来源于stack exchange,提问作者Ws7one
相关产品推荐
相关产品推荐

