记一次TextInput控件字符长度限制

工作上遇到这样一个需求,要封装一个可计数、限制字符数的文本框。无疑是要用TextInput控件。这个控件有一个maxLength属性,该属性可以限制文本框的最大字符数,但实测对于中文九宫格键盘联想区域输入的字符无法限制。

先说结论

我们封装了一个组件,内部是一个TextInput和一个用于计数的Text组件。属性如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
render() {
return (
<View style={styles.container}>
<TextInput
autoCorrect={false}
autoCapitalize='none'
style={styles.textInput}
placeholder={this.state.placeholder}
placeholderTextColor={'gray'}
multiline={true}
numbersOfLines={3}
blurOnSubmit={true}
onChangeText={(text)=>{this._onChangeText(text)}}
underlineColorAndroid='transparent'
value={this.state.text}
/>
<Text style={this.state.overflow?styles.limitRed:styles.limit}>
{this.state.limit-this.state.count}
</Text>
</View>
);
}

回调方法_onChangeText(text)代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
_onChangeText(text) {
let inputText = text.replace("\n","");
if (text.length > this.state.limit) {
this.setState({
text: inputText.substr(0, this.state.count),
});
} else {
this.setState({
text: inputText,
count: inputText.length,
});
}
}

遇到的问题

很自然地,把TextInput加上maxLength属性来限制字符数,然后遇到九宫格键盘联想输入无法限制的情况。紧接着想到在回调方法中,限制输入多少字符就截取前多少个字符。然后很自然地遇到了Emoji字符,截取不完整导致异常的问题。

根据异常的说明,是Emoji字符截取不完整导致异常:RCTJSONStringify() encountered the following error: The data couldn't be written because of an error in the content of the data.

没想到,将TextInputmaxLength属性删掉,就可以避免红屏。

但是当最后输入的是Emoji字符的时候,如果直接截取超过限制的字符,导致Emoji字符被分离,会显示一个错误字符。新版的Emoji字符有的占4个字符,有的占2个字符。避免这个问题也很简单,直接截取上一次输入的字符数即可,就完美地把本次输入的Emoji字符去掉了。