• トップ
  • ブログ一覧
  • 【ReactNative】KeyboardAvoidingViewでうまくスクロールしない時
  • 【ReactNative】KeyboardAvoidingViewでうまくスクロールしない時

    KeyboardAvoidingViewとは

    スマートフォンの仮想キーボードで表示が隠れないようにするViewです。

    これを設定すれば例えば以下のようにキーボードにTextInputが隠れてしまう場合などで、
    隠れない位置までスクロールしてくれるようになります。

    KeyboardAvoidingViewありKeyboardAvoidingViewなし

     

    キーボードに合わせてTextInputがうまくスクロールしない

    例えば以下のようなflexを用いたフォームの場合、

    1export default function RootLayout() {
    2  const [text, setText] = useState<string>('');
    3
    4  return (
    5    <SafeAreaProvider>
    6      <SafeAreaView className="h-full bg-white">
    7        <KeyboardAvoidingView behavior='padding'>
    8          <TouchableWithoutFeedback onPress={Keyboard.dismiss}>
    9            <View className='h-full'>
    10              <View className='m-5'>
    11                <Text className='text-3xl text-center text-slate-600'>タイトル</Text>
    12              </View>
    13              <View className='flex gap-10 p-5 pb-10 bg-gray-200'>
    14                <Text className='text-2xl text-center text-slate-600'>テキスト</Text>
    15                {[...new Array(5)].map((index) => (
    16                  <TextInput 
    17                    key={index}
    18                    className='w-full p-2 border border-gray-300 rounded text-2xl bg-neutral-50'
    19                    value={text} onChangeText={setText}
    20                    placeholder='TextInput'
    21                  />
    22                ))}
    23              </View>
    24              <View>
    25                <Text className='text-3xl text-center text-slate-600'>送信</Text>
    26              </View>
    27            </View>
    28          </TouchableWithoutFeedback>
    29        </KeyboardAvoidingView>
    30      </SafeAreaView>
    31    </SafeAreaProvider>
    32  );
    33}

    以下の画像の通り、キーボードに隠れる要素にフォーカスを当てた場合にうまく機能しない時があります。

     

    通常時キーボード出現時

    解決方法

    justyfy-endを利用した上で、最下部にflex-growのViewを入れることで解決できます。

    1export default function RootLayout() {
    2  const [text, setText] = useState<string>('');
    3
    4  return (
    5    <SafeAreaProvider>
    6      <SafeAreaView className="h-full bg-white">
    7        <KeyboardAvoidingView behavior='padding' className='h-full'>
    8          <TouchableWithoutFeedback onPress={Keyboard.dismiss}>
    9            <View className='h-full justify-end'>
    10              <View className='m-5'>
    11                <Text className='text-3xl text-center text-slate-600'>タイトル</Text>
    12              </View>
    13              <View className='flex gap-10 p-5 pb-10 bg-gray-200'>
    14                <Text className='text-2xl text-center text-slate-600'>テキスト</Text>
    15                {[...new Array(5)].map((index) => (
    16                  <TextInput 
    17                    key={index}
    18                    className='h-[50px] w-full p-2 border border-gray-300 rounded text-2xl bg-neutral-50'
    19                    value={text} onChangeText={setText}
    20                    placeholder='TextInput'
    21                  />
    22                ))}
    23              </View>
    24              <View>
    25                <Text className='text-3xl text-center text-slate-600'>送信</Text>
    26              </View>
    27              <View className='flex-grow' />
    28            </View>
    29          </TouchableWithoutFeedback>
    30        </KeyboardAvoidingView>
    31      </SafeAreaView>
    32    </SafeAreaProvider>
    33  );
    34}

    ただし上部側のTextInputのフォーカスでも同様のスクロールをしてしまうので、TextInputが多くある画面には向きません。

    その場合はKeyboardAwareScrollViewを利用しましょう!

    KeyboardAwareScrollViewを使った解決方法

    以下を参考に導入して、KeyboardAvoidingViewを置き換えるだけです。
    https://github.com/APSL/react-native-keyboard-aware-scroll-view

    1import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view'
    2
    3export default function RootLayout() {
    4  const [text, setText] = useState<string>('');
    5
    6  return (
    7    <SafeAreaProvider>
    8      <SafeAreaView className="h-full bg-white">
    9        <KeyboardAwareScrollView className='h-full'>
    10          <TouchableWithoutFeedback onPress={Keyboard.dismiss}>
    11            <View className='h-full'>
    12              <View className='m-5'>
    13                <Text className='text-3xl text-center text-slate-600'>タイトル</Text>
    14              </View>
    15              <View className='flex gap-10 p-5 pb-10 bg-gray-200'>
    16                <Text className='text-2xl text-center text-slate-600'>テキスト</Text>
    17                {[...new Array(5)].map((index) => (
    18                  <TextInput 
    19                    key={index}
    20                    className='h-[50px] w-full p-2 border border-gray-300 rounded text-2xl bg-neutral-50'
    21                    value={text} onChangeText={setText}
    22                    placeholder='TextInput'
    23                  />
    24                ))}
    25              </View>
    26              <View>
    27                <Text className='text-3xl text-center text-slate-600'>送信</Text>
    28              </View>
    29            </View>
    30          </TouchableWithoutFeedback>
    31        </KeyboardAwareScrollView>
    32      </SafeAreaView>
    33    </SafeAreaProvider>
    34  );
    35}

     

    上部フォーカス下部フォーカス

    KeyboardAvoidingViewの時だとjustify-end以外ではうまく動かないことがあるのですが、こちらは気にする必要なく動くので楽ですね!
    例えばjustify-betweenを利用したい場合は以下のようにViewを変更することで対応可能です。

    1<KeyboardAwareScrollView className='h-full'>
    2  <TouchableWithoutFeedback onPress={Keyboard.dismiss}>
    3    <View className='flex h-screen-safe justify-between'>

    ライトコードでは、エンジニアを積極採用中!

    ライトコードでは、エンジニアを積極採用しています!社長と一杯しながらお話しする機会もご用意しております。そのほかカジュアル面談等もございますので、くわしくは採用情報をご確認ください。

    採用情報へ

    おすすめ記事

    エンジニア大募集中!

    ライトコードでは、エンジニアを積極採用中です。

    特に、WEBエンジニアとモバイルエンジニアは是非ご応募お待ちしております!

    また、フリーランスエンジニア様も大募集中です。

    background