안녕하세요. RyuWoong 입니다.
오랜만에 뵙습니다! 최근 들어 여러 고민을 하며 공부를 했고 (차차 풀어보겠습니다. 😄) 재밌을만한 간단한 주제를 가져와 소개하게 되었습니다. React Native Library중에, React Native Aware Scroll View 라는 라이브러리가 있습니다. 문득 어떻게 동작하는 걸까라는 호기심이 생겨 라이브러리를 한번 파헤쳐봤어요! 함께 보시죠.
원리
원리는 생각보다 단순했어요. 그리고 숨겨진 RN의 Method들이 있다는 것도 알았죠!
원리는 간단하게 3단계로 나눌 수 있어요.
Input을 선택하면 이벤트가 동작 → 선택된 Input이 무엇인지 확인하고 해당 Input을 가져옴 → 해당 Input으로 Scroll 하도록 동작해요.
첫번째
"어떻게 Input을 선택하면 이벤트가 동작하게 하지?" 에 대한 방법은, Keybaord.addListener를 활용할 수 있어요.
Keybaord.addListener(’keyboardDidShow’, (e:KeyboardEvent) ⇒ {
// 내부 동작 입력
})
키보드가 나타나야 할 때마다 해당 이벤트가 동작해요. 이미 키보드가 올라와 있더라도 동작하기 때문에 아주 적절한 이벤트죠!
두번째
Focused Input이 무엇인지 알아야겠죠? 이는 아래 적은 함수를 사용하면 Focus된 Input을 가져올 수 있어요.
const textInput = TextInput.State.currentlyFocusedInput();
세번째
마지막으로 해당 Input으로 Scroll 해야겠죠? scrollView에는 아래와 같이 공식문서에는 없는 숨겨진 Method들이 있어요.
scrollRef.current?.scrollResponderScrollNativeHandleToKeyboard
scrollResponderScrollNativeHandleToKeyboard, 이 Method는 입력한 nodeId로 Scroll해주는 Method예요.
앞서 두번째에서 받아온 textInput의 nodeID를 가져와 볼까요? 이는 findNodeHandle라는 react native 내장 함수를 사용할 수 있어요.
const textInput = TextInput.State.currentlyFocusedInput();
const inputNodeId = findNodeHandle(textInput)
scrollRef.current?.scrollResponderScrollNativeHandleToKeyboard(
inputNodeId,
0, // offset
true // 키보드 상단에 Input이 맞도록 여부.
);
이렇게 하면, ScrollView내 Focus된 Input으로 Scroll합니다.
완성
대략적으로 작성한 예시예요.
import { NavigationOptions } from "@/components/category";
import globalStyle from "@/constants/globalStyle";
import { useEffect, useRef, useState } from "react";
import {
SafeAreaView,
findNodeHandle,
Keyboard,
KeyboardAvoidingView,
Platform,
Text,
TextInput,
ScrollView,
} from "react-native";
function ScrollInput() {
const [keyboardHeight, setKeyboardHeight] = useState(0);
const scrollRef = useRef<ScrollView>(null);
const getFocusedInputNodeId = () => {
const textInput = TextInput.State.currentlyFocusedInput();
if(!textInput){
return;
}
const inputNodeId = findNodeHandle(textInput);
return inputNodeId
}
const scrollToFocusedInput = (nodeId,offset, scroll) => {
if(!nodeId) {
return;
}
scroll.current?.scrollResponderScrollNativeHandleToKeyboard(
nodeId,
offset,
true
);
}
// 1. Keyboard Event Listener 등록, 키보드가 보여지면.
// 2. Focuse된 Input을 가져와서 NodeId를 찾아옴
// 3. 해당 NodeId로 이동하여 Scroll
// timeout는 약간의 지연을 줘서 올바르게 동작하게 하기 위함.
useEffect(() => {
Keyboard.addListener("keyboardDidShow", (e) => {
const height = e.endCoordinates.height;
setKeyboardHeight(height);
setTimeout(() => {
const nodeId = getFocusedInputNodeId();
scrollToFocusedInput(nodeId,height,scrollRef)
}, 250);
});
Keyboard.addListener("keyboardDidHide", (e) => {
setKeyboardHeight(0);
});
return () => {
Keyboard.removeAllListeners("keyboardDidShow");
Keyboard.removeAllListeners("keyboardDidHide");
};
}, []);
return ( <SafeAreaView style={globalStyle.Container}>
<ScrollView
ref={scrollRef}
keyboardDismissMode="none"
contentContainerStyle={{ paddingBottom: keyboardHeight }}
>
// ....
<ScrollView/>
</SafeAreaView>
)
}
export default ScrollInput;
마무리
꽤 오래된 라이브러리라 Class 기반으로 복잡하게 작성되어 있어서 처음엔 알아보기 힘들었지만, 핵심 포인트만 쏙쏙 빼서 정리해보았어요. 다른 분들에게도 도움이 됐으면 좋겠네요! 다음엔 다른 재밌는 이야기로 찾아 뵐게요.
'Front-End > React Native Issue' 카테고리의 다른 글
[React Native] React Native IDE (0) | 2024.05.15 |
---|---|
[React Native] Xcode 15.3 버전 이후 Build 시 Flipper Error (0) | 2024.03.24 |
[React Native] React Native 환경 변수 설정 하기. (0) | 2024.02.28 |
[React Native] DeepLink. (2) | 2023.05.29 |
[RN] 앱을 만들어보자, React Native! - App Icon 설정 .04 (0) | 2023.02.24 |
삽질의 기록과 일상을 남기는 블로그입니다. 주로 React Native를 다룹니다.
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!