Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

making a multiline, expanding TextInput with React-Native

I'm working on a react-native app and need a TextInput that has similar functionality to the textview in the "messages" app on iOS—it should start out as one line and then gracefully expand to more lines until some limit (like 5 lines of text) and then start scrolling along to latest line as needed.

Took a look at the SlackTextViewController but a) seems like it has a lot of stuff that I don't want and b) I'd like to try to keep as much code in React (and out of objective-C/swift) as possible.

Edit: Just want to emphasize that I would prefer REACT (JAVASCRIPT) code, as stated above, rather than Objective-C or Swift.

like image 945
Aaron Yodaiken Avatar asked Jul 17 '15 11:07

Aaron Yodaiken


People also ask

How do you make multiline TextInput in React Native?

To align text to the top multiline TextInput with React Native, we can set the textAlignVertical style to 'top' . to add the multiline prop to make the TextInput a multiline input. We set the numberOfLines to set the text input height to 5 lines high.

How do I resize TextInput React Native?

To implement auto grow multiline text input, you can adjust the height of the text input according to the content size in the textInput. you can use onContentSizeChange prop in TextInput and call a function to increase/decrease the height of input.

How do you wrap text in TextInput in React Native?

To achieve the same effect, you can wrap your TextInput in a View : import React, { Component } from 'react'; import { AppRegistry, View, TextInput } from 'react-native'; class UselessTextInput extends Component { render() { return ( <TextInput {... this.

What is multiline text field?

The Multiline field is similar to the Text field but allows for several lines of text. This field type allows you to enter a large amount of text based on the question or prompt. The benefit of using this type of field is that a Multiline field can hold up to 1 gigabyte of data or approximately two million characters.


2 Answers

I tried two different ways to do this today. Neither are the best but I thought I'd record my efforts in case they are helpful. They both definitely had the effect you are looking for, though sometime delayed with all the async communication.

1) Offscreen Text height

So just under the TextInput, I added a regular Text field with the same font and padding and such. I registered the onChange listener on the input and called setState({text: event.nativeEvent.text}). The Text filed got its value from the state. Both had onLayout Listeners. Basically, the goal was to get the height for the TextInput from the (unrestricted) Text. Then I hid the Text way offscreen

https://gist.github.com/bleonard/f7d748e89ad2a485ec34

2) Native Module

Really, I just needed the height of the content in the real UITextView. So I added a category to RCTUIManager as there are several methods there already that are helpful. I got rid of the hidden Text view. So onChange, I ask for the height and use that in the same way via the state.

https://gist.github.com/bleonard/6770fbfe0394a34c864b

3) Github PR

What I really hope is that this PR gets accepted. It looks to do something like this automatically.

https://github.com/facebook/react-native/pull/1229

like image 119
bleonard Avatar answered Oct 13 '22 13:10

bleonard


Adding multiline={true} to a TextInput will allow scrolling if the amount of text exceeds the available space. You can then change the height of the TextInput by accessing the nativeEvent.contentSize.height of the event from the onChange prop.

class Comment extends Component {    state = {       text: '',       height: 25    }     onTextChange(event) {      const { contentSize, text } = event.nativeEvent;       this.setState({         text: text,         height: contentSize.height > 100 ? 100 : contentSize.height      });     }     render() {       return (          <TextInput             multiline             style={{ height: this.state.height }}             onChange={this.onTextChange.bind(this)}             value={this.state.text}          />       );    } } 
like image 38
Groovietunes Avatar answered Oct 13 '22 12:10

Groovietunes