へなちょこSEの考察

0x22歳のへなちょこSEが、日々思うことを考察します。自社内、金融系を経て現在法人系PKG開発に従事。

【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"を設定してください。