(1) Отрегулируйте масштаб системного шрифта
(2) Изменить стиль шрифта системы (квадратный, красочный и т. Д.)
Масштабирование шрифта текстового компонента
В настройках мобильного телефона мы можем настроить размер шрифта, чтобы управлять отображением шрифтов мобильного телефона. В обычных условиях многие приложения не учитывают влияние изменения размера системного шрифта на пользовательский интерфейс. Поэтому, когда пользователь настраивает размер системного шрифта, текущий макет пользовательского интерфейса приложения нарушается, поскольку размер не подходит. Как быстро решить эту проблему? На самом деле официальное масштабирование шрифтов дает нам решение: allowFontScaling. Просто установите для этого свойства компонента Text значение false. При изменении размера системного шрифта размер текста в приложении не изменится соответствующим образом. На этом этапе мы можем добавить глобальную конфигурацию свойства для компонента Text в файл записи индекса и единообразно установить для компонента Text значение allowFontScaling в false.
import { Text } from 'react-native';
const TextRender = Text.render;
Text.render = function (...args) {
const originText = TextRender.apply(this, args);
const { style } = originText.props;
return React.cloneElement(originText, {
allowFontScaling: false,
});
};
Масштабирование шрифта компонента TextInput
Хорошо, мы рады открыть телефон, чтобы протестировать его. Внезапно обнаружил, что при входе в систему шрифт в поле ввода все равно меняется на системный. В TextInput мы можем установить размер шрифта с помощью стиля, поэтому можем ли мы также использовать allowFontScaling для управления им? Продолжайте изменять и добавлять для параметра allowFontScaling значение false глобально для компонента TextInput. В ходе эксплуатации выяснилось, что для iOS-устройств все нормально, а на Android-устройства эффекта нет. Таким образом, установка allowFontScaling для TextInput не решает проблему терминала Android. Как решить проблему на стороне Android? На самом деле мы можем воспользоваться PixelRatio.
Официальное объяснение PixelRatio выглядит следующим образом:
PixelRatio class gives access to the device pixel density.
переводить:
Класс PixelRatio предоставляет методы для доступа к плотности пикселей устройства.
В PixelRatio предусмотрено четыре API:
вgetFontScaleМожно получить масштабирование текущего размера шрифта. Официальное объяснение следующее:
Returns the scaling factor for font sizes. This is the ratio that is used to calculate the absolute font size, so any elements that heavily depend on that should use this to do calculations. If a font scale is not set, this returns the device pixel ratio. Currently this is only implemented on Android and reflects the user preference set in Settings > Display > Font size, on iOS it will always return the default pixel ratio. @platform android
Возвращает масштабирование размера шрифта. Это соотношение можно использовать для расчета абсолютного размера шрифта, поэтому многие компоненты, сильно зависящие от размера шрифта, необходимо вычислять с помощью результата этой функции. Если масштабирование шрифта не установлено, он напрямую возвращает плотность пикселей устройства. В настоящее время эта функция реализована только на устройствах Android, и она будет отражать «Настройки > Дисплей > Размер шрифта» в параметрах пользователя. На устройствах iOS он просто возвращает плотность пикселей по умолчанию.
Видно, что этот API в настоящее время поддерживает только использование платформы Android. На стороне iOS будут некоторые проблемы. Таким образом, мы можем использоватьgetFontScaleЧтобы решить проблему масштабирования шрифта TextInput на стороне Android:
размер шрифта = текущее значение размера шрифта / PixelRatio.getFontScale()
⚠️ Примечание. Для этого обходного пути не устанавливайте для параметра allowTextScaling значение false в TextInput на платформе Android.
Таким образом, общее решение выглядит следующим образом:
Инкапсулируйте функцию инструмента:
/**
* TextInput 组件字体适配
*/
import { PixelRatio, Platform } from 'react-native';
export default function (fontSize) {
return Platform.OS === 'android' ? fontSize / PixelRatio.getFontScale() : fontSize;
}
Он используется следующим образом:
textInputFont: { fontSize: TextInputFontResponsive(18),},
Настройте глобальные свойства TextInput в файле вводадля параметра allowTextScaling задано значение false.
import { TextInput, Platform } from 'react-native';
const TextInputRender = TextInput.render;
TextInput.render = function (...args) {
const originText = TextRender.apply(this, args);
const { style } = originText.props;
return React.cloneElement(originText, {
allowFontScaling: Platform.OS === 'android', // 只在iOS平台设置为false
});
};
стиль шрифта
Многие мобильные телефоны на внутреннем рынке могут установить системный стиль шрифта в виде root. Некоторые производители мобильных телефонов (Xiaomi, Huawei и др.) также предоставляют функцию прямой установки стиля системного шрифта без рута. Точно так же, когда мы устанавливаем стиль шрифта системы мобильного телефона, шрифт в приложении также изменится. Следующее может заключаться в том, что макет пользовательского интерфейса неупорядочен, и интерфейс не может быть унифицирован. Как показано ниже: Чтобы решить эту проблему, нам нужно контролировать стиль шрифта в приложении, чтобы он не менялся со стилем системы. Как это решить? Установите пользовательский дебют шрифта. Я не буду вдаваться в подробности того, как настроить шрифты в React Native. Вы можете обратиться к: Пользовательский шрифт в React Native Мы по-прежнему можем устанавливать пользовательские шрифты, устанавливая глобальные свойства, и изменение стиля системного шрифта не повлияет на стиль шрифта в приложении.
const TextRender = Text.render;
Text.render = function (...args) {
const originText = TextRender.apply(this, args);
const { style } = originText.props;
return React.cloneElement(originText, {
allowFontScaling: false,
style: [{
...PlatformStyle({ fontFamily: 'PingFangRegular' }),
}, style],
});
};
/**
* 根据平台设置对应样式
*/
import { Platform } from 'react-native';
export default function platformStyle(androidStyle = {}, iosStyle = {}) {
if (Platform.OS === 'android') {
return androidStyle;
}
return iosStyle;
}
Поскольку на платформе iOS нет проблем со стилем шрифта, мы используем PlatformStyle для различения настроек. Продолжай запускать приложение, черт возьми! ! Почему некоторые шрифты снова используют системные шрифты.
Как показано ниже:
Фактически, в React Native эта проблема возникает, когда мы устанавливаем свойство fontStyle или fontWeight для компонента Text. Святое дерьмо, это смущает, заставляет ли это меня идти против проекта дизайна и не выделять жирным шрифтом или курсивом? Это определенно невозможно, поэтому мы можем добиться этого, только установив соответствующий шрифт. Для унификации настройте для нас компонент Text:
import React, { Component } from 'react';
import { Text, StyleSheet, Platform } from 'react-native';
export default class TextWidget extends Component {
renderAndroidText() {
let { style, children } = this.props;
let fontStyle = null;
if (style) {
if (style instanceof Array) {
style = StyleSheet.flatten(style);
}
fontStyle = style.fontWeight ? {
fontWeight: 'normal',
fontFamily: 'PingFangBold',
} : { fontFamily: 'PingFangRegular' };
}
return (
<Text
{...this.props}
style={[ style, fontStyle ]}
>
{children}
</Text>
);
}
render() {
return Platform.OS === 'ios' ? <Text {...this.props} /> : this.renderAndroidText();
}
}
В приведенном выше компоненте мы выбираем соответствующий пользовательский шрифт, решая, следует ли снова установить свойство fontWeight. На самом деле вышесказанное все еще не идеально, если мы действительно хотим использовать определенный fontWeight или fontStyle, как нам это сделать?
Его можно установить по следующим правилам:
fontWeight: 300: "Light", 400: "Regular", 700: "Bold", 900: "Black", normal: "Regular", fontStyle: bold: "Bold" italic: "Italic"
Реализация примерно делится на следующее:
(1) Получите соответствующее имя шрифта, обнаружив fontWeight и fontStyle в атрибуте стиля, заданном Text.
(2) Отфильтруйте свойства fontWeight и fontStyle, чтобы убедиться, что для этих двух свойств нет настроек, иначе они будут недействительными.
Обнаружение свойства текста
// getFontFamily.js
// 包含所有字体
const fonts = {
SonglcyFont: {
fontWeights: {
300: "Light",
400: "Regular",
700: "Bold",
900: "Black",
normal: "Regular",
bold: "Bold"
},
fontStyles: {
normal: "",
italic: "Italic"
}
},
};
const getFontFamily = (baseFontFamily, styles = {}) => {
const { fontWeight, fontStyle } = styles;
const font = fonts[baseFontFamily];
const weight = fontWeight
? font.fontWeights[fontWeight]
: font.fontWeights.normal;
const style = fontStyle
? font.fontStyles[fontStyle]
: font.fontStyles.normal;
if (style === font.fontStyles.italic && weight === font.fontWeights.normal) {
return `${baseFontFamily}-${style}`;
}
return `${baseFontFamily}-${weight}${style}`;
};
export default getFontFamily;
Выше мы определили файл getFontFamily, в файле сначала мы устанавливаем константы шрифтов, в fonts объявляем все конфигурации шрифтов, используемые в проекте. Каждый шрифт содержит шрифт, соответствующий fontWeight, например, 300 соответствует шрифту в форме Light под шрифтом SonglcyFont. И так далее. В методе getFontFamily baseFontFamily — это имя шрифта, а styles — это стиль компонента Text. Затем в этом методе получите атрибут шрифта, соответствующий шрифтам, через имя шрифта, а затем оцените, содержит ли стиль компонента Text fontWeight, если да, выньте соответствующее имя шрифта, если нет, используйте стиль шрифта Regular. fontStyle такой же, как этот. Наконец, возвращается соответствующее имя шрифта. Пример: SonglcyFont-Light
Окончательный пользовательский компонент Text выглядит следующим образом:
import React from "react";
import { Text, StyleSheet } from "react-native";
import getFontFamily from "./getFontFamily";
// 过滤 fontWeight fontStyle 属性, 生成新的 style 对象
const omit = (obj, keys) => {
return Object.keys(obj)
.reduce((result, key) => {
if (!keys.includes(key)) {
result[key] = obj[key];
}
return result;
}, {});
};
const AppText = ({style, ...props}) => {
// Text style
const resolvedStyle = StyleSheet.flatten(style);
// 通过对 Text style 的检测,拿到对应自定义字体
const fontFamily = getFontFamily(resolvedStyle.fontFamily, resolvedStyle);
// 过滤掉 Text style 中的 fontWeight fontStyle 得到新的 style 对象
const newStyle = omit({...resolvedStyle, fontFamily},["fontStyle", "fontWeight"]);
return (
<Text
{...props}
style={newStyle}
/>
);
};
export default AppText;
В пользовательском компоненте Text выше мы сделали две вещи:
(1) Обнаружив стиль текста, получите соответствующий пользовательский шрифт.
(2) Отфильтруйте fontWeight fontStyle в текстовом стиле, чтобы получить новый объект стиля.
Наконец-то я могу повеселиться~
Суммировать
В этой статье представлен краткий обзор решения проблемы со шрифтами в React Native. Отбрасывая от начальной простой проблемы, шаг за шагом добиваться окончательного решения. Надеюсь, это поможет вам.