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

时间:2017-12-28 04:59:02

标签: android reactjs react-native

如何在视图中使本地文本的字体大小自动更改?

我有不同长度的文本,其中一些不适合视图,因此减小了字体大小。我查看了文档并找到了this 但它只适用于iOS,我需要Android版。

它是否适用于其他组件,如button和touchableopacity?

7 个答案:

答案 0 :(得分:3)

尝试这种方法。考虑根据屏幕宽度设置字体大小,如下所示

width: Dimensions.get('window').width

因此,在您的风格中尝试进行百分比计算以使字体大小适合屏幕

style={
  text:{
     fontSize:0.05*width
  }
}

这将适用于所有屏幕(Android和IOS)

答案 1 :(得分:0)

我在React Native应用程序中调整视图大小的文本数量(用户输入字符串到当前限制为30个字符的输入字段)中存在类似的问题。我注意到已经为iOS实现了一些属性:adjustsFontSizeToFit minimumFontScale={.4},但是Android目前没有可用的此类方法。

注意:该解决方案适用于我,但可能不是“最佳”解决方案!

当前,我正在使用嵌套的三元运算符:

fontSize: this.props.driverName.length > 12 && 
this.props.driverName.length < 20 ? heightPercentageToDP('2%') : 
this.props.driverName.length > 20 && this.props.driverName.length < 40 
? heightPercentageToDP('1.75%') : heightPercentageToDP('2.25%')

用外行的话来说,上述三进制检查所用字符的范围,并根据该范围将fontSize修改为视图内的'%'。方法:heightPercentageToDP是一种功能,我正在使用该功能根据移动屏幕的DP将尺寸转换为“%”(这样,它可以在平板电脑或移动电话上进行响应)。

heightPercentageToDP代码段:

    import { Dimensions, PixelRatio } from "react-native";
    const widthPercentageToDP = widthPercent => {
    const screenWidth = Dimensions.get("window").width;
    // Convert string input to decimal number
    const elemWidth = parseFloat(widthPercent);
    return PixelRatio.roundToNearestPixel((screenWidth * elemWidth) / 100);
    };
    const heightPercentageToDP = heightPercent => {
    const screenHeight = Dimensions.get("window").height;
    // Convert string input to decimal number
    const elemHeight = parseFloat(heightPercent);
    return PixelRatio.roundToNearestPixel((screenHeight * elemHeight) / 100);
    };
    export { widthPercentageToDP, heightPercentageToDP };

heightPercentageToDP的信用和来源为: https://medium.com/react-native-training/build-responsive-react-native-views-for-any-device-and-support-orientation-change-1c8beba5bc23

答案 2 :(得分:0)

您可以轻松使用小型图书馆,可以维护每台设备的字体大小。

npm i --save react-native-responsive-fontsize

从“ react-native-response-fontsize”导入RF

fontSize:RF(2)

但是不要忘记在文本中添加allowFontScaling = {false}道具。由于ios具有自动字体缩放功能,因此有时字体大小可能会与您的预期不同。

答案 3 :(得分:0)

尝试此方法。

我使用onLayout方法来实现这一目标。

首先,我将Text视图包装在固定大小的View中,然后为这两个视图实现onLayout,以便可以获取固定大小View的高度和Text视图的高度。

接下来,如果“文本”视图的所需高度大于“视图”的高度,我们将减小“文本”视图的字体大小,直到其高度适合我们的视图为止。

在此测试代码中,我创建了2个视图,一个为粉红色,一个为黄色背景,将调整粉色视图内Text的字体大小以适合该视图,而黄色Text将保持相同的字体大小。 / p>

import React, { useState, useEffect } from 'react';
import { StyleSheet, Text, View } from 'react-native';

export default function App() {
  const [size, setSize] = useState(20)
  const [viewHeight, setViewHeight] = useState(0)
  const [textHeight, setTextHeight] = useState(0)

  useEffect(() => {
    if (textHeight > viewHeight) {
      setSize(size - 1) // <<< You may adjust value 1 to a smaller value so the text can be shrink more precisely
    }
  }, [textHeight])

  return (
    <View style={styles.container}>
      <View
        style={{
          margin: 20,
          backgroundColor: 'pink',
          width: 200,
          height: 200
        }}
        onLayout={(event) => {
          var { x, y, width, height } = event.nativeEvent.layout;
          setViewHeight(height)
        }}
      >
        <Text
          style={{
            fontSize: size,
          }}
          onLayout={(event) => {
            var { x, y, width, height } = event.nativeEvent.layout;
            setTextHeight(height)
          }}
        >
          Gemma is a middle grade novel that follows a curious explorer and her ring-tailed lemur, Milo, 
          as they hunt for the “most greatest treasure in the world”. Solving riddles, battling a bell-wearing 
          jaguar, and traveling the Eight Seas, Gemma’s adventures take her from a young girl to a brave captain, 
          whose only limits are the stars.
        </Text>
      </View>

      <View
        style={{
          margin: 20,
          backgroundColor: 'yellow',
          width: 200,
          height: 200
        }}
      >
        <Text
          style={{
            fontSize: 20
          }}
        >
          Gemma is a middle grade novel that follows a curious explorer and her ring-tailed lemur, Milo, 
          as they hunt for the “most greatest treasure in the world”. Solving riddles, battling a bell-wearing 
          jaguar, and traveling the Eight Seas, Gemma’s adventures take her from a young girl to a brave captain, 
          whose only limits are the stars.
        </Text>
      </View>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
});

您可能会注意到,当字体大小减小时,粉红色的Text字体正在收缩动画,我建议您可以将Text opacity设置为0,并在字体调整完成后将其设置为1,这样用户就不会看到丑陋的动画。

答案 4 :(得分:0)

改进了Jeffy Lee代码对我有用

const AdjustLabel = ({
  fontSize, text, style, numberOfLines
}) => {
  const [currentFont, setCurrentFont] = useState(fontSize);

  return (
    <Text
      numberOfLines={ numberOfLines }
      adjustsFontSizeToFit
      style={ [style, { fontSize: currentFont }] }
      onTextLayout={ (e) => {
        const { lines } = e.nativeEvent;
        if (lines.length > numberOfLines) {
          setCurrentFont(currentFont - 1);
        }
      } }
    >
      { text }
    </Text>
  );
};

答案 5 :(得分:0)

最近我面临着更具挑战性的任务。任务是在相同视图的视图(每个视图中每个单词一个词)中容纳多个具有不同长度的单词(例如:Plane和Truck具有相同的字符数,但是以相同的字体大小,Truck的长度比Plane长。)尺寸。我使用React Native Animated库来实现这一点。 输入字词->飞机,卡车,公共汽车,汽车,驾驶室

  1. 使用“文本”组件以固定的字体(最好是较大的字体大小,超过最长的单词所需的宽度)呈现所有给定的单词。
  2. 使用文本组件的onLayout函数找到最长单词的长度。
  3. 沿着X轴计算比例系数(由于步骤1中的假设,该比例系数将小于1)。该比例系数适用于视图中最长的单词。
  4. 然后在用Animated.View组件包装的Animated.Text组件中呈现每个单词,该组件具有在步骤2中计算出的固定长度。
  5. 将上述所有动画组件的ScaleX属性从1转换为比例因子。
  6. 将所有Animated.Text组件的ScaleY属性从1转换为比例因子。 (所有动画的持续时间都设置为0毫秒)
  7. 使用反应状态管理和/或CSS样式隐藏绝对定位的所有Text组件。

我实现了上述想法,因为在算法运行期间,无论我使用了哪种技巧来隐藏字体,都不断减小字体大小,直到单词适合使用onLayout的View在屏幕上对用户可见为止。这是我用来开发更强大的代码的基本实现。

import React, {useCallback, useEffect, useRef, useState} from 'react';
import {Animated, View} from 'react-native';

const ScaleText = props => {
  const {word, wordLength, fontWeight} = props;
  const [calculatedLength, setCalculatedLength] = useState(0);
  const [animationEnded, setAnimationEnded] = useState(false);
  const scaleViewAnimation = useRef(new Animated.Value(0)).current;

  const scalingAnimation = useCallback(() => {
    Animated.timing(scaleViewAnimation, {
      toValue: wordLength / calculatedLength,
      duration: 0,
    }).start(() => {
      setAnimationEnded(true);
    });
  }, [calculatedLength, scaleViewAnimation, wordLength]);

  useEffect(() => {
    if (calculatedLength && !animationEnded) {
      scalingAnimation();
    }
  }, [animationEnded, calculatedLength, scaleViewAnimation, scalingAnimation]);

  return (
    <View style={{width: wordLength, justifyContent: 'center', flex: 1}}>
      <Animated.Text
        onLayout={event => {
          let {width} = event.nativeEvent.layout;
          setCalculatedLength(width);
        }}
        numberOfLines={1}
        adjustsFontSizeToFit={true}
        style={[
          {...props},
          {
            fontWeight: fontWeight || 'normal',
            fontSize: Math.floor((30 * 4 * wordLength) / (110 * word.length)),
            transform: [{scaleX: scaleViewAnimation}],
            textAlign: 'center',
            position: 'absolute',
          },
        ]}>
        {word}
      </Animated.Text>
    </View>
  );
};



export default function App() {
  return (
    <View style={{width: '100%', height: '100%', flexDirection: 'row'}}>
      {['Chamoda', 'Me', 'Nanayakkara'].map((e, i) => (
        <View style={{flex: 1, aspectRatio: 1}} key={i}>
          <ScaleText fontWeight={'bold'} word={e} wordLength={80} />
        </View>
      ))}
    </View>
  );
}

答案 6 :(得分:-4)

实现基于分辨率的字体大小的最佳方法是使用像素比率,我已经在我的应用程序中实现了这种方法。 像素比率可以帮助您实现这一目标。像素比越小意味着分辨率越低,像素比越高分辨率越高。

  

PixelRatio.get()=== 1 mdpi Android设备(160 dpi)

     

PixelRatio.get()=== 1.5 hdpi Android设备(240 dpi)

     

PixelRatio.get()=== 2 iPhone 4,4S iPhone 5,5c,5s iPhone 6 xhdpi   Android设备(320 dpi)

     

PixelRatio.get()=== 3 iPhone 6 plus xxhdpi Android设备(480 dpi)

     

PixelRatio.get()=== 3.5 Nexus 6

下面的代码片段是样式表,你可以使用JSX代码中的类

import { StyleSheet, PixelRatio } from 'react-native'
import { Colors } from '../../Themes/'
const FONT_SIZE = 12;
FONT_SIZE_Requests = 12;
if ((PixelRatio.get() <= 1.5) &&(PixelRatio.get() > 1)) {
  FONT_SIZE = 9;
  FONT_SIZE_Requests = 9;
} else if (PixelRatio.get() <=1) {
  FONT_SIZE = 9;
  FONT_SIZE_Requests=9;
} else if ((PixelRatio.get() > 1.5) &&( PixelRatio.get() >= 2) && (PixelRatio.get() < 3)) {
         FONT_SIZE = 10;
         FONT_SIZE_Requests = 10;
       } else if (PixelRatio.get() >= 3) {
         FONT_SIZE = 11;
         FONT_SIZE_Requests = 11;
       }
export default StyleSheet.create({
  header: {
    backgroundColor: Colors.ClayColor
  },
  transparentHeader: {
    backgroundColor: "#ffffff",
    elevation: 0
  },
labelStyle:{
   margin:0,
        fontFamily:'roboto_medium',
        fontSize:FONT_SIZE
},
labelStyleRequests:{
  margin:0,
  fontFamily:'roboto_medium',
  fontSize:FONT_SIZE_Requests
}
})