3

After entering text in TextInput I want to know the currunt number of lines in TextInput. Or The current number of strings is also possible.

I've tried string.split('\n').length, but this code does not detect that the line is automatically incremented when the text is larger than the screen.

How do I get the number of lines

When I make this feature in Swift Implemented using the string.enumerateLines function.

Do you have a similar function?

Tim
  • 10,459
  • 4
  • 36
  • 47
oijafoijf asnjksdjn
  • 1,115
  • 12
  • 35

3 Answers3

6

As far as I know, there is no offical way to get the currently used number of lines, but I have a workaround for you:

We make use of the onLayout method of our TextInput and we keep track of the currently used height. We need two state variables:

this.state = {
      height: 0, // here we track the currently used height
      usedLines: 0,// here we calculate the currently used lines 
    }

onLayout:

  _onLayout(e) {
     console.log('e', e.nativeEvent.layout.height);
     // the height increased therefore we also increase the usedLine counter
     if (this.state.height < e.nativeEvent.layout.height) {
         this.setState({usedLines: this.state.usedLines+1}); 
     } 
     // the height decreased, we subtract a line from the line counter 
     if (this.state.height > e.nativeEvent.layout.height){
         this.setState({usedLines: this.state.usedLines-1}); 
     }
     // update height if necessary
     if (this.state.height != e.nativeEvent.layout.height){
         this.setState({height: e.nativeEvent.layout.height});
     }

  }

Render Method

  render() {
    console.log('usedLines', this.state.usedLines);
    return (
      <View style={styles.container}>
        <TextInput multiline style={{backgroundColor: 'green'}} onLayout={(e)=> this._onLayout(e)} />
      </View>
    );
  }

Working Example:

https://snack.expo.io/B1vC8dvJH

Tim
  • 10,459
  • 4
  • 36
  • 47
0

For react-native version >= 0.46.1

You can use onContentSizeChange for a more accurate line track, for example with react hooks as following:

     /**
     * used to tracker content height and current lines
     */
    const [contentHeightTracker, setContentHeightTracker] = useState<{
        height: number,
        usedLines: number;
    }>({
        height: 0,
        usedLines: 0
    });
    useEffect(() => {
        // console.log('used line change : ' + lineAndHeightTracker.usedLines);
        // console.log('props.extremeLines : ' + props.extremeLines);
        if (contentHeightTracker.usedLines === props.extremeLines) {
            if (extremeHeight.current === undefined) {
                extremeHeight.current = contentHeightTracker.height;
            }
        }
        //callback height change
        if (contentHeightTracker.height !== 0) {
            props.heightChange && props.heightChange(contentHeightTracker.height,
                contentHeightTracker.usedLines >= props.extremeLines,
                extremeHeight.current);
        }
    }, [contentHeightTracker]);
    const _onContentHeightChange = (event: NativeSyntheticEvent<TextInputContentSizeChangeEventData>) => {
        // console.log('event height : ', event.nativeEvent.contentSize.height);
        // console.log('tracker height : ', lineAndHeightTracker.height);
        // the height increased therefore we also increase the usedLine counter
        if (contentHeightTracker.height < event.nativeEvent.contentSize.height) {
            setContentHeightTracker({
                height: event.nativeEvent.contentSize.height,
                usedLines: contentHeightTracker.usedLines + 1
            });
        } else {
            // the height decreased, we subtract a line from the line counter
            if (contentHeightTracker.height > event.nativeEvent.contentSize.height) {
                setContentHeightTracker({
                    height: event.nativeEvent.contentSize.height,
                    usedLines: contentHeightTracker.usedLines - 1
                });
            }
        }
    };
render() {
    console.log('usedLines', this.state.usedLines);
    return (
      <View style={styles.container}>
        <TextInput 
           multiline 
           style={{backgroundColor: 'green'}} 
           onContentSizeChange={_onContentHeightChange}
        />
      </View>
    );
  }
DeepCode
  • 11
  • 1
0

The other solutions might fail if the user:

  • Highlights a lot of lines and deletes them all at once
  • Pastes a lot of lines at once

One way to solve this issue would be to set a lineHeight to the <TextInput> and use the onContentSizeChange prop:

<TextInput
    style={{
        lineHeight: 20,
    }}
    onContentSizeChange={e =>
        console.log(e.nativeEvent.contentSize.height / 20) // prints number of lines
    }
/>
RivasCVA
  • 91
  • 2
  • 8