原因は不明ですが、React-NativeではAndroid版TextInputのmultilineがうまく機能しない場合があるようです。
前提
こんな感じのTextInputを想定しています。
<TextInput multiline blurOnSubmit={false} onChange={this.onChange} />
確認できた症例
ハードウェアキーボードから改行が入力できない
シミュレーターを利用した状況下で、PCのキーボード側からEnterキーを入力しても改行が入力されません。
日本語入力用ソフトウェアキーボードから改行が入力できない
シミュレーターを利用した状況下で、Androidのソフトウェアキーボードからリターンキーを入力しても改行が入力されません。
英語入力用ソフトウェアキーボードからは改行が入力できる
同様にシミュレーター利用下で、Androidの英語入力用キーボードからリターンキーを押すと、期待通り改行が入力されます。
改行が入力できない時は送信イベントが発火する
前2つの状況下では、改行が入力されない代わりにonSubmitEditing
イベントが発火しました。これは以下の仕様に反する動作です。
onSubmitEditing?: PropTypes.func
Callback that is called when the text input’s submit button is pressed. Invalid if
multiline={true}
is specified.
対症療法
直接の対応方法は調べても見つかりません。発見できたのはリターンキーに反応して改行を挿入するという対症療法だけでした。
幸いにして、改行が入力されない場合にはonSubmitEditing
イベントが発火するため、これを利用します。
render() { return ( <TextInput multiline blurOnSubmit={false} onChange={this.onChange} value={this.state.text} selection={this.state.selection} onSelectionChange={this.onSelectionChange} onSubmitEditing={this.onSubmitEditing} /> ); } onSelectionChange(event) { this.setState({ selection: event.nativeEvent.selection, }); } onSubmitEditing = _.debounce(this._onSubmitEditing, 100, true); _onSubmitEditingNote() { const { text, selection } = this.state; const newText = `${text.substr(0, selection.start)}\n${text.substr(selection.end, text.length)}`; if (selection.start === text.length) { this.setState({ text: newText }); } else { this.setState({ text: newText, selection: { start: selection.start + 1, end: selection.end + 1, }, }); } }
改行入力後のカーソル位置変更のためだけのために、selectionをstateに突っ込まなきゃいけないので処理が増えてあまりきれいではありません。 もっと良い方法があればよいのですが。
参考
- TextInput multiline={true} not functioning as expected · Issue #12717 · facebook/react-native
- [TextInput] Multiline doesn’t work with certain keyboards on android · Issue #13159 · facebook/react-native
- https://github.com/wix/react-native-autogrow-textinput/issues/18
- TextInput – React Native | A framework for building native apps using React