React NativeのTextInputで改行に応じて入力ボックスの高さ(スタイル)を変更したい


こんにちは!

今回は「React Native TextInputで改行に応じて入力ボックスのスタイルを変更する」方法について、お伝えしていきたいと思います。

今回は以下のような簡単な入力ボックスを例に説明していきたいと思います。

改行したかどうかを取得するにはonContentSizeChangeを使う

まず、前提として、改行を有効にするにはTextInputmultiline={true}を設定しておきます。

<TextInput
  multiline={true}
/>

次にTextInputpropsonContentSizeChangeを設定します。

export default function SplashScreen() {
const [inputMsg, setInputMsg] = useState('');
return (
  <TextInput
    style={{fontSize: 50}}
    multiline={true}
    value={inputMsg}
    onContentSizeChange={(event) => {
      console.log(event.nativeEvent.contentSize); //例:Object {"height": 60, "width": 32,}
}
    }
  />
);

これは入力値が変わるたびに呼ばれるコールバック関数で、 { nativeEvent: { contentSize: { width, height } } }を取得することができます。
今回はこのheightの値を使用します。

widthは文字数に応じて変化し、heightは改行によって変化します。
※フォントサイズなどによって、変化量も異なります。

例を使いながら、これらの値がどのように変化していくのかみていきます。

例1 1文字入力した時

出力結果は・・・

  <TextInput
    style={{fontSize: 50}}
    multiline={true}
    value={inputMsg}
    onContentSizeChange={(event) => {
      console.log(event.nativeEvent.contentSize); 
      //出力結果: Object {"height": 60, "width": 32,}
}
    }
  />
);

例2 1文字入力+改行1回した時

  <TextInput
    style={{fontSize: 50}}
    multiline={true}
    value={inputMsg}
    onContentSizeChange={(event) => {
      console.log(event.nativeEvent.contentSize); 
      //出力結果: Object {"height": 119.66666666666667, "width": 32,}
}
    }
  />
);

heightの値が大きくなっていることがわかります。
この値を使って、入力ボックスのスタイルを変更したいと思います。

改行に応じて、入力ボックスのスタイルを変更する

改行すると、動的に入力ボックスの高さを広げるようにしてみます。
先ほどのnativeEvent.contentSize.heightstateで管理します。

export default function SplashScreen() {
  // 入力ボックスの高さはstateで管理
  const [inputHeight, setInputHeight] = useState(0);
  return (
    <View style={styles.container}>
      <View
        style={[
          // 入力ボックスの高さ = nativeEvent.contentSize.height
          styles.inputContainer, {height: inputHeight},
        ]}
      >
        <TextInput
          style={{fontSize: 50}}
          placeholder="type here..."
          multiline={true}
          onContentSizeChange={(event) => {
            // 入力ボックスの高さをsetState
            setInputHeight(event.nativeEvent.contentSize.height);
          }}
        />
      </View>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems:'center',
    justifyContent:'center',
  },
  inputContainer: {
    backgroundColor: 'yellow',
    width: 300,
  },
});

入力ボックスの高さに上限を設定する

すでに動的に入力ボックスの高さを設定することができました。
しかし、今のままだと入力ボックスが画面いっぱいまで広がってしまいます。

高さに上限を設定するために条件分岐を追加します。


// (省略)

<TextInput
  style={{fontSize: 50}}
  placeholder="type here..."
  multiline={true}
  onContentSizeChange={(event) => {
    console.log(event.nativeEvent.contentSize);
   /* 入力の高さが300より大きい場合は上限値300を設定する */
    if (event.nativeEvent.contentSize.height <= 300) {
      setInputHeight(event.nativeEvent.contentSize.height);
    } else {
      setInputHeight(300);
    }
  }}
/>

// (省略)

これによって、高さに上限値を設定することができました。(今回は上限4行になるように調整しています)

まとめ

だいぶ簡単に書いてしまいましたが、
上記のように書くことで、入力ボックスの高さを変更することができます。
よかったら試してみてください。

参考

React Native公式ドキュメント
https://reactnative.dev/docs/scrollview