【Expo (React Native/Android)】BottomTabNavigation + Admob + GiftedChatでキーボードが入力エリアを隠してしまう問題
React Nativeアプリを開発中に、タイトルの問題に当たって解決したので記録しておきます。
開発環境
ExpoSDK:35 Androidはシミュレータ(Pixel3)と実機(SO-02G)で確認
package.jsonの抜粋
"expo": "^35.0.0",
"expo-ads-admob": "^7.0.0",
"expo-constants": "~7.0.0",
"react-native": "https://github.com/expo/react-native/archive/sdk-35.0.0.tar.gz",
"react-native-gifted-chat": "^0.9.11",
"react-navigation": "^4.0.6",
"react-navigation-stack": "^1.8.1",
"react-navigation-tabs": "^2.5.5",
事象
Expo使って開発していて、BottomTabNavigation + Admob + GiftedChatを使っている画面があります。 この画面でチャットの文字を入力しようとすると、入力エリアがキーボードに隠されてしまいました。
対策1:KeyboardAboidingViewの追加
GiftedChatのGithubを確認したところ、Androidの場合は"KeyboardAboidingView"を使うようにとのこと。 見逃していたため追加しました。
[https://github.com/FaridSafi/react-native-gifted-chat#notes-for-android:title]
<View style={{ flex: 1 }}> <GiftedChat /> { Platform.OS === 'android' && <KeyboardAvoidingView behavior="padding" /> } </View>
ただ、この方法だけだと結局うまくいきませんでした。
対策2:ReactNavigationのヘッダーの高さ分Offset設定
いろいろ調べたら「ReactNavigationのヘッダーを使っているとうまくいかないよ」という書き込みを見つけたので、その書き込みの通り対応してみることに。
まずimportに下記を追加
import { Header } from 'react-navigation-stack';
続いて先ほどのKeyboardAboidingViewにkeyboardVerticalOffsetを設定しました。
<KeyboardAvoidingView keyboardVerticalOffset={Header.HEIGHT} behavior="padding" />
動作を確認すると、微妙に動いてくれたんですが、まだ隠れている・・・。 これ、他にもoffsetに足さなきゃダメなんじゃね?ということでさらに調べる。
対策3:ステータスバーの高さ分Offsetを追加
たぶんステータスバーも影響してんだろ、ということでExpoの機能を使ってステータスバーの高さを取得します。
importに下記を追加
import Constants from 'expo-constants';
で、Offsetに追加
<KeyboardAvoidingView keyboardVerticalOffset={Header.HEIGHT + Constants.statusBarHeight} behavior="padding" />
これでもまだ足りず。 あぁそうか、Admobだ。 しかもAdmobはSmartBannerにしてるから高さ可変だぞ。
対策4:Admobの高さ分Offsetを追加
ExpoのAdmobでサイズをsmartBannerPortraitに指定している場合、iOSの場合は高さ固定ですが、Androidだと端末の画面サイズに応じて広告の高さが変わります。 なので、値を以下の通り設定。
let adHeight = 32; if (Dimensions.get('window').height > 400 && Dimensions.get('window').height < 720) { adHeight = 50; } else if (Dimensions.get('window').height > 720) { adHeight = 90 }
で、これをまたOffsetに足しこむ。
<KeyboardAvoidingView keyboardVerticalOffset={Header.HEIGHT + Constants.statusBarHeight + adHeight} behavior="padding" />
うまく動きました!
補足:BottomTabNavigationの設定
BottomTabNavigationでtabBarOptionsを使っている場合、"keyboardHidesTabBar"は"false"を設定してください。