본문 바로가기
FE Development/React-Native

트러블 슈팅 - 키보드가 UI를 가리는 경우 (KeyboardAvoidingView)

by 개발자 데이빗 2021. 11. 25.

문제가 되었던 사항

android의 경우 버튼을 하단에 위치시키면 키보드가 올라올때 자동으로 버튼이 키보드 위로 올라가게 된다.

그러나 ios의 경우 키보드가 올라와도 버튼이 제자리에 있어 키보드를 내린 후 버튼을 클릭해야 하는 불편함이 생기게 되었다.

 

해결방안

React Native에서 제공하는 KeyboardAvoidingView를 컴포넌트화하여 해당 문제가 발생하는 UI에 적용하였다.

키보드 높이를 구해 키보드만큼 버튼의 높이를 올리려고 하였으나 디바이스마다 키보드의 높이가 달라 몇가지 문제가 있었다.

1. keyboardVerticalOffset에 keyboardHeight을 그대로 전달하였으나 너무 높이 올라가 0.1씩 수정해가며 3.4라는 수치를 찾음

2. 3.4라는 수치는 찾았으나 keyboardHeight을 구하는 방법의 문제가 있었다.

useState의 초기값만큼 버튼이 위치한 이후에 event를 구독하기 때문에 화면 진입과 동시에 포커싱하는 경우 버튼이 올라오지 않고 다시 포커싱이 되었을때 제대로 올라오는 문제

const KeyBoardAvoid = ({ children, aosOffset = 0 }) => {
  const [keyboardHeight, setKeyboardHeight] = useState();
  
  useEffect(() => {
    const handleKeyboardEvents = (e) => {
      setKeyboardHeight(e.endCoordinates.height);
    };

    Keyboard.addListener('keyboardWillShow', handleKeyboardEvents);

    return () => {
      Keyboard.removeListener('keyboardWillShow', handleKeyboardEvents);
    };
  }, []);

  return (

    <KeyboardAvoidingView
      keyboardVerticalOffset={Platform.OS === 'ios' ? keyboardHeight / 3.4 : aosOffset}
      behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
    >
      {children}
    </KeyboardAvoidingView>
  );
};

 

 

아래 블로그에 같은 문제를 해결하신 글을 발견하여 2가지 문제를 해결할 수 있었다. (정말 감사합니다.)

다만 아직까지도 왜 statusBar 높이에 44를 더한 값을 keyboardVerticalOffset에 전달했을때 키보드 높이에 맞게 올라가는지에 대해서는 찾아보는 중이다..

https://coding-w00se.tistory.com/17

 

[React Native] 입력창-키보드 겹치는 문제 - ios

채팅, 댓글 기능이 들어간 앱에서는 일반적으로 아래와 같이 정보들은 위쪽에 입력창이 아래쪽에 배치되어 있는 화면을 갖게 됩니다. 이번 게시글에는 React-Native에서 위와 같은 스크린을 작업할

coding-w00se.tistory.com

 

여하튼 최종적으로 아래와 같은 컴포넌트를 만들어 필요한 경우에 사용할 수 있었다.

const KeyBoardAvoid = ({ children, aosOffset = 0 }) => {
  const [statusBarHeight, setStatusBarHeight] = useState(0);
  useEffect(() => {
    if (Platform.OS === 'ios') {
      StatusBarManager.getHeight((statusBarFrameData) => {
        setStatusBarHeight(statusBarFrameData.height);
      });
    }
  }, []);

  return (
    <KeyboardAvoidingView
      keyboardVerticalOffset={Platform.OS === 'ios' ? 44 + statusBarHeight : aosOffset}
      behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
    >
      {children}
    </KeyboardAvoidingView>
  );
};

 

 

 

댓글