【React Native】TextInputがキーボードに隠れてしまう問題の解決法について にて npm で簡単に解決する方法があります。package.json の dependencies を増やしたくない方はこちらをどうぞ。
現象
スクリーンショットにある様に ScrollView の下の方に TextInput が配置されていると、ソフトウェアキーボードが表示されると TextInput が隠れてしまいます。
これは困った。
勝手にこのようになってもらいたいものですよね。
解決方法
以下、サンプルソースコード。
import React, {Component} from 'react';
import ReactNative, {
Keyboard,
ScrollView,
StyleSheet,
TextInput,
View
} from 'react-native';
export default class MyComponent extend Component {
constructor(props) {
super(props);
}
componentWillMount() {
this.keyboardWillShowListener = Keyboard.addListener('keyboardWillShow', this._handleKeyboardWillShow.bind(this));
}
componentWillUnmount() {
this.keyboardWillShowListener.remove();
}
render() {
return (
<ScrollView
ref={(component) => this._scrollview = component}
style={styles.container}
>
<View
style={styles.dummy}
/>
<TextInput
ref={(component) => this._textinput = component}
style={styles.input}
/>
<View
style={styles.dummy}
/>
</ScrollView>
);
}
_handleKeyboardWillShow() {
const responder = this._scrollview.getScrollResponder();
responder.scrollResponderScrollNativeHandleToKeyboard(
ReactNative.findNodeHandle(this._textinput),
100,
true
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'column'
},
dummy: {
height: 1000
},
input: {
height: 44,
borderWidth: 1,
borderColor: '#000000'
}
});
keyboardWillShow でソフトウェアキーボードが表示されたかどうか監視します。表示されたら ScrollView から getScrollResponder()
して scrollResponderScrollNativeHandleToKeyboard()
します。第一引数に TextInput の node handle が必要になりますので、ReactNative.findNodeHandle()
で取得しましょう(React.findNodeHandle()
は削除されているので ReactNative
の方を使ってください)。第二引数でキーボードからどのくらい上にスクロールさせるか offset を指定できます。0 にするとちょうど見えなくなってしまいますので、ご自身で良い感じの数値を指定してください。今回は 100 を指定しています。第三引数を true にしておけば、算出されるスクロール値がマイナスになった時 0 にしてくれます。
ちなみに、TextInput の onFocus でスクロールさせようとしてはいけません。ソフトウェアキーボードがまだ表示されていないにも関わらず、フォーカスが当たった時点でスクロールさせようとしてしまいます。結果、正常なスクロール値が算出できず、期待通りに動いてくれません。setTimeout() でタイミングをずらしてあげてもよいのですが、せっかく keyboardWillShow があるのでそちらを使いましょう。
まとめ
getScrollResponder()
とか scrollResponderScrollNativeHandleToKeyboard()
は Docs に記載されていません。IDE を使っているとコードジャンプしてくれるので楽に辿ることができます。この機会に React Native 自体のソースコードを見てみるのも良いですね。
また、そもそも ScrollView に配置されていないとスクロールさせることはできませんので、TextInput は ScrollView と併用ですね。今回は ScrollView ですが、ListView でも同様のことができると思います(未検証ですが)。