react-native: 키보드를 열면 입력란이 숨겨지는 문제 해결

React Native의 <TextInput>에 포커스가 닿으면 iOS에서는 키보드가 아래에서 올라와 UI 위에 겹치지만 React Native는 입력란이 화면에 보이는 상태로 표시되어 있을 때까지는 번거로움을 봐 아니.

예를 들어, 입력란이 화면의 최하부에 있는 것 같은 UI에서는, 입력란이 키보드로 단단히 숨어 버린다.



해결책으로서는, 컴퍼넌트측에서 키보드의 개폐 이벤트를 받아, 키보드가 표시되었을 때, UI를 위로 어긋나게 하는 처리를 코딩한다.

UI를 어긋나게 하는 방법으로서, merginTop 에 마이너스치를 세트 하는, height 를 감소시키는 등의 방법을 시도해 보았던 것의 계산이나 조정이 어려웠다. 궁극적으로 진정된 것은 키보드와 같은 높이의 <View>를 화면 하단에 추가하는 방법.

아래의 애니메이션은 이 방법을 구현한 데모로, 파란 부분이 키보드와 같은 높이의 <View> 로 되어 있다.



이 키보드용 스페이스 컴퍼넌트의 실장은 다음과 같이 된다.

KeyboardSpace.js
import React, {Component} from "react-native";
const {
  Animated,
  DeviceEventEmitter
} = React;

export default class KeyboardSpace extends Component {
  constructor(props, context) {
    super(props, context);
    this.state = {
      height: new Animated.Value(0)
    };
    this.keyboardWillShowSubscription = null;
    this.keyboardWillHideSubscription = null;
  }

  componentDidMount() {
    DeviceEventEmitter.addListener("keyboardWillShow", (e) => this.keyboardWillShow(e));
    DeviceEventEmitter.addListener("keyboardWillHide", (e) => this.keyboardWillHide(e));
  }

  componentWillUnmount() {
    this.keyboardWillShowSubscription.remove();
    this.keyboardWillHideSubscription.remove();
  }

  keyboardWillShow(e) {
    Animated.timing(this.state.height, {
      toValue: e.endCoordinates ? e.endCoordinates.height : e.end.height,
      duration: e.duration
    }).start();
  }

  keyboardWillHide(e) {
    Animated.timing(this.state.height, {
      toValue: 0,
      duration: e.duration
    }).start();
  }

  render() {
    return (
      <Animated.View style={{height: this.state.height}}></Animated.View>
    );
  }
}

사용법은, 어긋나고 싶은 컴퍼넌트의 뒤에 둘 뿐.
import React, {Component} from "react-native";
const {
  View,
  StyleSheet
} = React;
import KeyboardSpace from "./KeyboardSpace.js";

export default class ConversationPage extends Component {
  render() {
    return (
      <View style={styles.container}>
        ...ずらしたいコンポーネントをここに配置...
        <KeyboardSpace />
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1
  }
});

덧붙여 애니메이션이 iOS의 키보드 출입 속도와 다르지만, React Native가 제공하고 있는 easing 커브에 iOS의 "keyboard"상당한 것이 없기 때문에 이렇게 되어 버린다. React Native의 Animated에서는 easing 커브를 커스텀 할 수도 있으므로, 신경이 쓰이는 경우는 미세 조정해 보세요…

좋은 웹페이지 즐겨찾기