りゅうちゃん(エンジニア)
【ReactNative】KeyboardAvoidingViewでうまくスクロールしない時
りゅうちゃん(エンジニア)
2025.01.16
IT技術
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'>
ライトコードでは、エンジニアを積極採用中!
ライトコードでは、エンジニアを積極採用しています!社長と一杯しながらお話しする機会もご用意しております。そのほかカジュアル面談等もございますので、くわしくは採用情報をご確認ください。
採用情報へ