React Native 响应式字体大小

Posted

技术标签:

【中文标题】React Native 响应式字体大小【英文标题】:React Native Responsive Font Size 【发布时间】:2016-02-11 06:04:21 【问题描述】:

我想问一下如何响应原生句柄或响应式字体。例如在 iphone 4s 我有 fontSize: 14,而在 iphone 6 我有 fontSize: 18.

【问题讨论】:

如果有人正在寻找完全禁用字体缩放的方法,请使用Text.defaultProps.allowFontScaling=false @CoderDave 这太棒了! 如果你想要基于屏幕大小的相对字体大小而不是精确的字体大小,你可以试试npmjs.com/package/react-native-responsive-dimensions,它会根据设备的屏幕大小自动调整你的字体大小 【参考方案1】:

因为响应式单元目前在 react-native 中不可用,我想说你最好的办法是检测屏幕尺寸,然后使用它来推断设备类型并有条件地设置 fontSize。

你可以这样写一个模块:

function fontSizer (screenWidth) 
  if(screenWidth > 400)
    return 18;
  else if(screenWidth > 250)
    return 14;
  else  
    return 12;
  

您只需要查看每个设备的默认宽度和高度。如果在设备改变方向时宽度和高度被翻转,您可能可以使用纵横比,或者只计算两个维度中较小的一个来计算宽度。

此module 或this one 可以帮助您查找设备尺寸或设备类型。

【讨论】:

我已经安装了 react-native-device 但是当我运行应用程序时它给了我一个“无法解析模块维度”的错误 听起来你需要确保为模块使用正确版本的 RN 我正在使用最新版本的 React Native :) 我认为它目前不受支持? 可能...也许尝试删除您的 node_modules 文件夹并重新npm install【参考方案2】:

您可以使用PixelRatio

例如:

var React = require('react-native');

var StyleSheet, PixelRatio = React;

var FONT_BACK_LABEL   = 18;

if (PixelRatio.get() <= 2) 
  FONT_BACK_LABEL = 14;


var styles = StyleSheet.create(
  label: 
    fontSize: FONT_BACK_LABEL
  
);

编辑:

另一个例子:

import  Dimensions, Platform, PixelRatio  from 'react-native';

const 
  width: SCREEN_WIDTH,
  height: SCREEN_HEIGHT,
 = Dimensions.get('window');

// based on iphone 5s's scale
const scale = SCREEN_WIDTH / 320;

export function normalize(size) 
  const newSize = size * scale 
  if (Platform.OS === 'ios') 
    return Math.round(PixelRatio.roundToNearestPixel(newSize))
   else 
    return Math.round(PixelRatio.roundToNearestPixel(newSize)) - 2
  

用法:

fontSize: normalize(24)

您可以更进一步,允许在每个 &lt;Text /&gt; 组件上使用预定义大小的大小。

例子:

const styles = 
  mini: 
    fontSize: normalize(12),
  ,
  small: 
    fontSize: normalize(15),
  ,
  medium: 
    fontSize: normalize(17),
  ,
  large: 
    fontSize: normalize(20),
  ,
  xlarge: 
    fontSize: normalize(24),
  ,
;

【讨论】:

你在哪里使用了你的 const 比例? 这似乎没有任何作用。迷你总是 === 12 为什么非 ios 设备要减去 2? @chinloong 谢谢这很好用,但是为什么在 android 上是 -2? 它不起作用,例如,对于 iPhone 12 mini 和 iPhone X,因为它们都有宽度 375 和像素比 3。虽然很明显,布局和字体大小应该注意差异.【参考方案3】:

看看我写的库:https://github.com/tachyons-css/react-native-style-tachyons

它允许您在启动时指定一个 root-fontSize (rem),您可以根据您的 PixelRatio 或其他设备特性进行设置。

然后你会得到与你的 rem 相关的样式,不仅是 fontSize,还有 paddings 等:

<Text style=[s.f5, s.pa2, s.tc]>
     Something
</Text>

扩展:

f5始终是您的基本字体大小 pa2 为您提供相对于基本字体大小的填充。

【讨论】:

【参考方案4】:

我们使用我们编写的简单、直接、可扩展的 utils 函数:

import  Dimensions  from 'react-native';
const  width, height  = Dimensions.get('window');

//Guideline sizes are based on standard ~5" screen mobile device
const guidelineBaseWidth = 350;
const guidelineBaseHeight = 680;

const scale = size => width / guidelineBaseWidth * size;
const verticalScale = size => height / guidelineBaseHeight * size;
const moderateScale = (size, factor = 0.5) => size + ( scale(size) - size ) * factor;

export scale, verticalScale, moderateScale;

为您节省一些时间来做许多 ifs。您可以在my blog post 上阅读更多相关信息。


编辑:我认为将这些函数提取到他们自己的 npm 包中可能会有所帮助,我还在包中包含了ScaledSheet,这是StyleSheet 的自动缩放版本。 你可以在这里找到它:react-native-size-matters。

【讨论】:

谢谢,使用这个工具的最佳方案是什么?我的意思是在哪里使用scale、verticaleScale和moderateScale? 我在几乎所有需要缩放的东西上都使用了中等缩放,比如字体大小、边距、图像和 Svg 大小(对于布局我使用 flex),因为 imo 缩放不应该是线性的,但这是个人喜好问题.如果您想获得线性结果,则主要使用比例,并在容器高度等内容上使用verticalScale。 过度使用在性能方面可以吗?【参考方案5】:

我通过执行以下操作设法克服了这个问题。

    为当前视图选择您喜欢的字体大小(确保 它看起来很适合您正在使用的当前设备 模拟器)。

    import Dimensions from 'react-native' 并定义宽度 像这样在组件之外:let width = Dimensions.get('window').width;

    现在 console.log(width) 并把它写下来。如果你的字体好看 例如,尺寸为 15,宽度为 360,然后取 360 和 除以 15 (= 24)。这将是重要的价值 会适应不同的尺寸。

    在您的样式对象中使用此数字,如下所示:textFontSize: fontSize = width / 24 ,...

现在你有了一个响应式字体大小。

【讨论】:

嘿,它真的有效吗? f1 = width/ (width/size) 这不行吗? 我最终使用了react-native-text c0dezer019.medium.com/thank-you-3824cb7b886c 和 medium.com/nerd-for-tech/… 这与@walter 相同,加上四舍五入等。谢谢老兄。 是的,我的解决方案并不完美,但它适用于我的用例!【参考方案6】:

你可以使用这样的东西。

var height, width = Dimensions.get('window'); var textFontSize = 宽度 * 0.03;

inputText: 
    color : TEXT_COLOR_PRIMARY,
    width: '80%',
    fontSize: textFontSize

希望这有助于在不安装任何第三方库的情况下。

【讨论】:

0.03 是从哪里来的? 它会响应吗?【参考方案7】:

我只是使用屏幕大小的比例,这对我来说很好。

const  width, height  = Dimensions.get('window');

// Use iPhone6 as base size which is 375 x 667
const baseWidth = 375;
const baseHeight = 667;

const scaleWidth = width / baseWidth;
const scaleHeight = height / baseHeight;
const scale = Math.min(scaleWidth, scaleHeight);

export const scaledSize =
    (size) => Math.ceil((size * scale));

测试

const size = 
    small: scaledSize(25),
    oneThird: scaledSize(125),
    fullScreen: scaledSize(375),
;

console.log(size);

// iPhone 5s
small: 22, oneThird: 107, fullScreen: 320
// iPhone 6s
small: 25, oneThird: 125, fullScreen: 375
// iPhone 6s Plus
small: 28, oneThird: 138, fullScreen: 414

【讨论】:

这是否意味着您必须使用 iPhone 6 模拟器,并且根据它在那里的外观,它在其他设备上看起来也不错? @WalterMonecke 在我的情况下是的。您也可以适应使用其他模拟器作为基础。【参考方案8】:

我最近遇到了这个问题,最终使用了react-native-extended-stylesheet

您可以根据屏幕尺寸设置rem 值和附加尺寸条件。根据文档:

// component
const styles = EStyleSheet.create(
  text: 
    fontSize: '1.5rem',
    marginHorizontal: '2rem'
  
);
// app entry
let height, width = Dimensions.get('window');
EStyleSheet.build(
  $rem: width > 340 ? 18 : 16
);

【讨论】:

【参考方案9】:
import  Dimensions  from 'react-native';

const  width, fontScale  = Dimensions.get("window");

const styles = StyleSheet.create(
    fontSize: idleFontSize / fontScale,
);

fontScale 根据您的设备获取规模

【讨论】:

fontscale 在我正在使用的 Android Emulator 4_WVGA_Nexus_S_API 虚拟设备上只返回 1。【参考方案10】:

我们可以使用 flex 布局并使用 adjustsFontSizeToFit=true 来获得响应式字体大小。并且文本会根据容器的大小进行调整。

     <Text
    adjustsFontSizeToFit
    style=styles.valueField>value
    </Text>

但在样式中,您还需要设置一个字体大小,然后adjustsFontSizeToFit 才会起作用。

    valueField: 
    flex: 3,
    fontSize: 48,
    marginBottom: 5,
    color: '#00A398',
,

【讨论】:

【参考方案11】:

adjustsFontSizeToFitnumberOfLines 为我工作。他们将长电子邮件调整为 1 行。

<View>
  <Text
    numberOfLines=1
    adjustsFontSizeToFit
    style=textAlign:'center',fontSize:30
  >
    this.props.email
  </Text>
</View>

【讨论】:

根据文档 'adjustsFontSizeToFit' 仅适用于 iOS 它也适用于 android @mdehghani 对我也有用,这篇文章应该被接受为正确答案! 我可以确认它适用于 Android 和 iOS!这正是我一直在寻找的。应该是正确答案。【参考方案12】:

为什么不使用PixelRatio.getPixelSizeForLayoutSize(/* size in dp */);,它和Android 中的pd 单位一样。

【讨论】:

【参考方案13】:

需要这种方式我用过这个,效果很好。

react-native-responsive-screen npm install react-native-responsive-screen --save

就像我有一台 1080x1920 的设备

The vertical number we calculate from height **hp**
height:200
200/1920*100 = 10.41% - height:hp("10.41%")


The Horizontal number we calculate from width **wp**
width:200
200/1080*100 = 18.51% - Width:wp("18.51%")

它适用于所有设备

【讨论】:

【参考方案14】:

一种稍微不同的方法对我有用:-

const normalize = (size: number): number => 
  const scale = screenWidth / 320;
  const newSize = size * scale;
  let calculatedSize = Math.round(PixelRatio.roundToNearestPixel(newSize))

  if (PixelRatio.get() < 3)
    return calculatedSize - 0.5
  return calculatedSize
;

请参考Pixel Ratio,因为这可以让您更好地根据设备密度设置功能。

【讨论】:

【参考方案15】:

我通常用这个:

import React from 'react';
import  View, Text, StyleSheet, Dimensions  from 'react-native';

var heightY = Dimensions.get("window").height;

export default function App() 
  return (
    <View style=styles.container>
      <Text style=styles.textStyle>fontSize heightY * 0.014</Text>
    </View>
  )


const styles = StyleSheet.create(
  container: 
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  ,
  textStyle: 
    fontSize: heightY * 0.014,
  
)

我们的想法是根据屏幕高度获取fontSize。计算示例:

// Height 785,.. -> fontSize = 11 
// Height 1000 -> fontSize = 14
// Height 1285,.. -> fontSize = 18

如果您希望它取决于您的屏幕宽度,您也可以尝试使用它:

var widthX = Dimensions.get("window").width;

【讨论】:

以上是关于React Native 响应式字体大小的主要内容,如果未能解决你的问题,请参考以下文章

如何在 React Native for Android 中调整字体大小以适应视图?

React Native 设置字体大小以填充父级

具有不同字体大小(首字母,首字母)的 react-native 嵌套文本

React-Native:如何缩放字体大小以支持 Android 和 iOS 中的许多不同分辨率和屏幕?

移动设备的 HTML 响应式字体大小

带有 rem 的响应式排版 - 以 % 或 px 为单位的基线字体大小?