React Native: Determine number of lines of Text component

前端 未结 4 1108

As the title says, I\'ve been trying to find a way to determine the number of lines the text component AFTER it has been given text. Look at my example below.



        
相关标签:
4条回答
  • 2020-12-06 09:49

    You can use this formula:

    CPL = Width / (font-size / font-constant)

    font-constant = a constant specified to each font. CPL = number of characters per line

    Here's some fonts with their constant:

     - Serif Fonts:
     American Typewriter — 2.14
     Baskerville — 2.14
     Georgia — 1.91
     Times New Roman — 2.21
    
     - Sans-serif Fonts:
     Arial — 1.91
     Calibri — 2.1
     Helvetica Neue — 1.9
     Lucida Grande — 1.91
     Tahoma — 1.91
     Trebuchet MS — 2.11
     Verdana — 1.73
    
     - Monospace Font:
     Courier New — 1.64
    

    for example:

    function getNumberOfLines(text, fontSize, fontConstant, containerWidth){
    
        let cpl = Math.floor(containerWidth / (fontSize / fontConstant) );
        const words = text.split(' ');
        const elements = [];
        let line = '';
    
        while(words.length > 0){
            if(line.length + words[0].length + 1 <= cpl || line.length === 0 && words[0].length + 1 >= cpl){
                let word = words.splice(0,1);
                if(line.length === 0){
                    line = word;
                }else {
                    line = line + " " + word;
                }
                if(words.length === 0){
                    elements.push(line);
                }
            }
            else {
                elements.push(line);
                line = "";
            }
        }
        return elements.length;
    }
    
    0 讨论(0)
  • I want to provide a modern solution. There is now a onTextLayout event that includes an array of lines which can be determined what number of lines are being rendered. There's other details in the lines array like actual height and width of every line which can be further used to determine if the text is being truncated.

    const NUM_OF_LINES = 5;
    const SOME_LONG_TEXT_BLOCK = 'Lorem ipsum ...';
    
    function SomeComponent () { 
      const [ showMore, setShowMore ] = useState(false);
      const onTextLayout = useCallback(e => {
        setShowMore(e.nativeEvent.lines.length > NUM_OF_LINES);
      }, []);
    
      return (
        <Text numberOfLines={NUM_OF_LINES} onTextLayout={onTextLayout}>
          {SOME_LONG_TEXT_BLOCK}
        </Text>
      );
    }
    
    0 讨论(0)
  • 2020-12-06 09:52

    It looks like React Native 0.24 implements an onLayout function
    http://facebook.github.io/react-native/docs/text.html#onlayout

    onLayout function
    Invoked on mount and layout changes with
    {nativeEvent: {layout: {x, y, width, height}}}

    So it looks like you could pass an onLayout callback function, get the height of the Text component and then do some calculations using the line height to get to the number of lines

    0 讨论(0)
  • 2020-12-06 10:11

    The solution Garrett McCullough have provided seem working for me, and I just want to add some code example:

    import React from 'react';
    import { StyleSheet, Text, View, TouchableHighlight } from 'react-native';
    
    const styles = StyleSheet.create({
        text: {
          fontSize: 24,
          lineHeight: 30,
        }
    });
    
    export default class App extends React.Component {
    
        onLayout = e => {
            const { height } = e.nativeEvent.layout;
            this.count = Math.floor(height / styles.text.lineHeight)
        }
    
        render() {
            return (
                <View style={styles.page}>
                  <Text onLayout={this.onLayout} style={styles.text}>
                    Random text. Random text. Random text. Random text. Random text. Random text. Random text.
                    Random text. Random text. Random text. Random text. Random text. Random text. Random text.
                    Random text. Random text. Random text. Random text. Random text. Random text. Random text.
                    Random text. Random text. Random text. Random text. Random text. Random text.
                  </Text>
    
                  <TouchableHighlight onPress={() => alert(`text lines count is ${this.count}`)}>
                    <Text style={{ fontSize: 50 }}>touch me!</Text>
                  </TouchableHighlight>
                </View>
            );
        }
    }
    

    https://snack.expo.io/@devastr1/text-lines-count-example

    0 讨论(0)
提交回复
热议问题