LoginSignup
0
1

More than 3 years have passed since last update.

React Nativeで画面回転時のレイアウト崩れに対応したら、KeyboardAvoidingViewが効かなくなった

Last updated at Posted at 2020-06-26

以下の2本立てです。

  • React Nativeで画面回転したらAndroidの場合にレイアウトが崩れてしまったので対応した
  • 今度はKeyboardAvoidingViewが効かなくなったので代替策で回避した

環境

  • React Native 0.61.5
  • iOS 13.5.1
  • Android 10

React Nativeで画面回転したらレイアウト崩れが発生した

KeyboardAvoidingViewをrootに配置した画面をPortrait=>Landscape=>Portraitと回転させると、謎の空間が発生。AndroidでFlexが正しく動いていないような挙動をしました。

名称未設定_001.png

ソースはこのような感じです。

対応前
class Hoge extends React.Component {
  render() {
    return (
      <KeyboardAvoidingView
        style={{
          flex: 1
        }}
        behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
      >
        // ...
      </KeyboardAvoidingView>
    );
  }
);

色々と解決方法を探して手当り次第試してみたところ、StackOverflowで見つけた方法で、stateを介して再renderさせるようにすることで正しくレイアウトされるようになりました。

対応後
class Hoge extends React.Component {
  _onLayout = () => {
    this.setState({ width: Dimensions.get('window').width }); 
  }

  render() {
    return (
      <KeyboardAvoidingView
        onLayout={this._onLayout}
        style={{
          flex: 1,
          width
        }}
        behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
      >
        // ...
      </KeyboardAvoidingView>
    );
  }
);

これにて一件落着・・と思いきや、、

今度はKeyboardAvoidingViewが効かなくなった

上記の対応を行うことで、iOS・Androidともに、KeyboardAvoidingViewがキーボードを避けないただのViewと化してしまいました。

Viewの入れ子関係を入れ替えたり、色々試してみたがうまくいかず。結局KeyboardAvoidingViewをあきらめ、代わりにKeyboardSpacerというライブラリを使うとうまくいきました。

対応後(改)
class Hoge extends React.Component {
  _onLayout = ({nativeEvent}) => {
    const width = Dimensions.get('window').width;
    const height = Dimensions.get('window').height;
    const screenOffset = height - nativeEvent.layout.height;
    this.setState({ width, screenOffset });
  };

  render() {
    return (
      <View
        onLayout={this._onLayout}
        style={{
          flex: 1,
          width
        }}
        behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
      >
        // ...
        <KeyboardSpacer topSpacing={(-1) * this.state.screenOffset} />
      </View>
    );
  }
);

はじめはAndroidで思うように機能しませんでしたが、AndroidManifestに windowSoftInputMode="adjustResize" を指定するとうまく動くようになりました。

また、ReactNavigationのBottomTabNavigatorを使用しているため、WindowのサイズとViewのサイズの差分を計算し、 KeyboardSpacertopSpacing に設定しています。

おわりに

画面回転つながりで、iPhoneでLandscapeにしたときにステータスバーが消える影響でレイアウトが崩れる問題も発生していたので、ステータスバーの高さをstoreで管理するようにしたりしました。
こういう小細工が色々と必要なのがツラいところです。

そろそろ温泉にでも行きたいですねぇ。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1