Reputation: 317
If set multiline as true, React Native will accept unlimited lines in TextInput, there has maxLength but it just limits the maximum number of characters, so how to set maximum lines on TextInput?
Upvotes: 14
Views: 40157
Reputation: 641
I was solving this same issue. Here's what I came up with. You can either remove the last trailing newline, or all of them. Both work differently, so use accordingly to how you want yours to function. I personally chose the remove last trailing newline alternative:
function onChangeText(text) {
if (props.multiline) {
const newlines = (text.match(/\n/g) || '').length + 1;
if (newlines > MAX_LINES) {
props.setState(text.replace(/\n$/, "")); // Remove last trailing newline
// props.setState(text.replace(/\n+$/, "")); // Remove all trailing newlines
return;
}
}
props.setState(text);
return;
};
Upvotes: 0
Reputation: 511
I solved the limit issue using maxHeight,numberOfLine and multiline prop
<TextInput placeholder="description here" numberOfLines={3} maxHeight={60} onChangeText={t => setDescription(t)} multiline={true} style={{ margin: 10, borderRadius: 20, padding: 5, borderWidth: 1 }} />
Upvotes: 1
Reputation: 1739
I created a simple version to extend the TextInput to give the maxLines feature.
import React, { Component } from "react";
import { TextInput } from "react-native";
import PropTypes from "prop-types";
export default class MultiLine extends Component {
static propTypes = {
maxLines: PropTypes.number
};
constructor(props) {
super(props);
this.state = {
value: props.value || ""
};
}
onChangeText = text => {
const { maxLines, onChangeText } = this.props;
const lines = text.split("\n");
if (lines.length <= (maxLines || 1)) {
onChangeText(text);
this.setState({ value: text });
}
};
render() {
const { onChangeText, multiline, value, ...other } = this.props;
return (
<TextInput
{...other}
multiline={true}
value={this.state.value}
onChangeText={this.onChangeText}
/>
);
}
}
A example:
<Multiline
value={this.state.testeText}
maxLines={10}
onChangeText={text => {
this.setState({ testeText: text });
}}
/>
Upvotes: 7
Reputation: 11
numberOfLines doesn't nothing in android too
You can do something like this
In Component state
this.state = {height: 35};
In JSX TextInput declaration
style={[styles.default, {height: Math.min(Math.max(35, this.state.height),120)}]}
Upvotes: 0
Reputation: 1591
You can use maxHeight
and minHeight
to accept what you want. For standard text fontSize, giving maxHeight={60}
will make TextInput scrollable after 3 lines. This is good for IOS - for Android you can use numberOfLines
prop.
Upvotes: 16
Reputation: 41
I have implemented the following component for an app I'm the owner. It is tested only on a restricted environment, so it probably has to be adapted to your need. I am sharing here with the hope it helps the community.
react-native: 0.46.3
import React, { Component } from 'react'
import { TextInput, Platform } from 'react-native'
const iosTextHeight = 20.5
const androidTextHeight = 20.5
const textHeight = Platform.OS === 'ios' ? iosTextHeight : androidTextHeight
class TextInputLines extends Component {
state = { height: textHeight * 2, lines: 1 }
componentWillReceiveProps (nextProps) {
if (nextProps.value === '') {
this.setState({ height: textHeight * 2, lines: 1 })
}
}
render () {
const {style, value, placeholder, numberOfLines = 8, autoFocus = true, onChangeText} = this.props
return (
<TextInput
style={[style, { height: this.state.height }]}
multiline
autoFocus={autoFocus}
value={value}
placeholder={placeholder}
onChangeText={(text) => onChangeText(text)}
onContentSizeChange={(event) => {
const height = Platform.OS === 'ios'
? event.nativeEvent.contentSize.height
: event.nativeEvent.contentSize.height - androidTextHeight
const lines = Math.round(height / textHeight)
const visibleLines = lines < numberOfLines ? lines : numberOfLines
const visibleHeight = textHeight * (visibleLines + 1)
this.setState({ height: visibleHeight, lines: visibleLines })
}}
underlineColorAndroid='transparent'
/>
)
}
}
export default TextInputLines
How to use:
import TextInputLines from './TextInputLines'
Within your render() method:
<TextInputLines
style={textStyle}
autoFocus={true}
value={this.state.value}
placeholder={textPlaceholder}
onChangeText={onChangeText}
numberOfLines={10}
/>
Upvotes: 4
Reputation: 317
It seems no props or packages to quickly implement checking number of lines, so I use javascript function match
to get the number from TextInput, then if the number reach the max value, do something to limit it.
Upvotes: 0
Reputation: 1177
I don't think you can on iOS. As mentioned, Android has the prop numberOfLines
. The closest I can think of would be to try to estimate the width of your input and limit the characters based on that dimension but it's my opinion that it may be a dark path to go down.
Should you choose to do so, someone was trying to get the number of lines here. A combination of the onLayout
function to get the width of your TextInput and onChangeText
to limit it might work.
Upvotes: 0