LoginSignup
15
11

More than 5 years have passed since last update.

React Native で TextInput がソフトウェアキーボードに隠れてしまう問題の対処方法

Posted at

【React Native】TextInputがキーボードに隠れてしまう問題の解決法について にて npm で簡単に解決する方法があります。package.json の dependencies を増やしたくない方はこちらをどうぞ。

現象

スクリーンショットにある様に ScrollView の下の方に TextInput が配置されていると、ソフトウェアキーボードが表示されると TextInput が隠れてしまいます。

スクリーンショット 2017-01-10 16.04.45.png

これは困った。

スクリーンショット 2017-01-10 16.04.51.png

勝手にこのようになってもらいたいものですよね。

スクリーンショット 2017-01-10 16.04.33.png

解決方法

以下、サンプルソースコード。

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 でも同様のことができると思います(未検証ですが)。

15
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
11