반응형
해당 글에서는 react-native 환경에서 ScrollView로 최상단, 최하단을 이동했을 때 이벤트를 발생시키는 동작 처리 방법에 대해 알아봅니다.
1) ScrollView의 최상단, 최하단으로 이동시 동작 처리 방법
💡ScrollView의 최상단, 최하단으로 이동시 동작 처리 방법
- Scroll로 이동을 하였을 때, 최상단일 때와 최하단일 때에 대해서 특정 이벤트를 발생시키는 동작 처리를 확인해 봅니다.
1. ScrollView
💡ScrollView
- React Native에서 제공하는 스크롤 가능한 컨테이너 컴포넌트입니다. 이 컴포넌트는 내부의 콘텐츠가 화면 크기를 초과할 때 유용하게 사용됩니다.
💡[참고] ScrollView 속성
속성 | 설명 |
onScroll | 스크롤 이벤트가 발생할 때 호출되는 함수입니다. |
onScrollBeginDrag | 사용자가 스크롤을 시작할 때 호출되는 함수입니다. |
onScrollEndDrag | 사용자가 스크롤을 끝냈을 때 호출되는 함수입니다. |
onScrollToTop | iOS에서 상태 바를 탭하여 스크롤이 최상단으로 이동할 때 호출되는 함수입니다. |
scrollEventThrottle | 스크롤 이벤트 발생 빈도를 조절합니다. 값은 밀리초 단위입니다. |
scrollEnabled | 스크롤 가능 여부를 설정합니다. 기본값은 true입니다. |
contentContainerStyle | ScrollView 내부 컨텐츠의 스타일을 지정합니다. |
horizontal | 가로 스크롤을 활성화합니다. 기본값은 false입니다. |
showsHorizontalScrollIndicator | 가로 스크롤바 표시 여부를 설정합니다. |
showsVerticalScrollIndicator | 세로 스크롤바 표시 여부를 설정합니다. |
refreshControl | 새로고침 컨트롤을 추가합니다. |
keyboardShouldPersistTaps | 키보드가 열려있을 때 탭 동작을 설정합니다. |
onContentSizeChange | 컨텐츠 크기가 변경될 때 호출되는 함수입니다. |
onMomentumScrollBegin | 스크롤 모멘텀이 시작될 때 호출되는 함수입니다. |
💡[참고] 더 많은 속성에 대해 궁금하시면 아래의 공식사이트를 확인하시면 도움이 됩니다.
2. 적용 이전 확인
💡적용 이전 확인
- 아래와 같은 형태의 글이 있고, 디바이스 높이 사이즈를 넘어가다 보니 이에 대해 스크롤 뷰를 적용하였습니다.
import React from "react"
import { Text, View } from "react-native"
import { ScrollView } from "react-native-gesture-handler";
const TestScreen = ({ navigation, route }) => {
return (
<>
<View style={{ height: "100%" }}>
<ScrollView>
<Text style={{ marginBottom: 150 }}>
<Text style={{ fontSize: 20 }}>작은 토끼와 큰 당근 {"\\n"}</Text>
옛날 옛적에 작은 토끼 한 마리가 살았어요. 이 토끼는 당근을 아주 좋아했답니다.{"\\n"}
어느 날, 토끼는 정원에서 엄청나게 큰 당근을 발견했어요. 그 당근은 토끼보다 두 배나 컸죠!{"\\n"}
"와! 이렇게 큰 당근은 처음 봐요!" 토끼가 말했어요.{"\\n"}
토끼는 그 큰 당근을 집으로 가져가고 싶었지만, 너무 무거워서 혼자서는 들 수 없었어요.{"\\n"}
그때 친구들이 나타났어요. 다람쥐, 두더지, 그리고 생쥐였죠.{"\\n"}
"우리가 도와줄게!" 친구들이 말했어요.{"\\n"}
모두 함께 힘을 모아 당근을 들어올렸어요. 그리고 토끼의 집으로 가져갔답니다.{"\\n"}
토끼는 친구들과 함께 맛있는 당근 요리를 만들어 나눠 먹었어요.{"\\n"}
"혼자서는 할 수 없었지만, 친구들과 함께라면 무엇이든 할 수 있어요!" 토끼가 행복하게 말했답니다.{"\\n"}
그 후로 토끼와 친구들은 더욱 사이좋게 지냈답니다. 끝.
</Text>
<Text>
<Text style={{ fontSize: 20 }}>황금 물고기의 소원{"\\n"}</Text>
옛날 옛적에 가난한 어부가 살았어요. 그는 매일 바다에 나가 물고기를 잡았답니다.{"\\n"}
어느 날, 어부는 반짝이는 황금 물고기를 잡았어요. 그런데 놀랍게도 그 물고기가 말을 했어요!{"\\n"}
"제발 나를 놓아주세요. 그러면 당신의 소원을 세 가지 들어드릴게요."{"\\n"}
어부는 깜짝 놀랐지만, 물고기를 놓아주었어요.{"\\n"}
"첫 번째 소원은 무엇인가요?" 물고기가 물었어요.{"\\n"}
"우리 집이 좀 더 크고 편안했으면 좋겠어요." 어부가 말했어요.{"\\n"}
순식간에 어부의 집은 아름다운 저택으로 변했어요.{"\\n"}
"두 번째 소원은요?" 물고기가 다시 물었어요.{"\\n"}
"풍요로운 정원이 있었으면 좋겠어요." 어부가 대답했어요.{"\\n"}
그러자 저택 주변에 아름다운 정원이 생겼어요.{"\\n"}
"마지막 소원은 무엇인가요?" 물고기가 물었어요.{"\\n"}
어부는 잠시 생각하다가 말했어요. "더 이상 바라는 게 없어요. 지금 이대로 행복합니다."{"\\n"}
황금 물고기는 미소 지으며 말했어요. "당신의 만족하는 마음이 가장 큰 행복의 비결이에요."{"\\n"}
그 후로 어부는 가족과 함께 행복하게 살았답니다. 끝.{"\\n"}
</Text>
</ScrollView>
</View>
</>
)
}
export default TestScreen
2) 최상단/최하단으로 이동 시 특정 영역이 출력되는 활용예시
💡최상단/최하단으로 이동 시 특정 영역이 출력되는 활용예시
- 해당 예시에서는 최상단 혹은 최하단으로 이동했을 시 특정 영역이 보이는 화면을 출력하는 예시입니다.
1. 최상단으로 스크롤을 올렸을 경우, 최상단의 화면에 “최상단의 영역 일 경우 해당 화면이 나옵니다~”로 출력이 됩니다.
2. 중간 영역으로 스크롤을 했을 경우, 최상단, 최하단 화면에 출력되는 영역이 모두 사라집니다.
3. 최하단으로 스크롤을 내렸을 경우, 최하단의 화면에 “최하단의 영역 일 경우 해당 화면이 나옵니다~”로 출력이 됩니다.
💡활용 예시 설명
1. handlerScrollView
- 해당 부분에서는 ScrollView에서 이용하는 이벤트를 관리합니다.
1.1. isAtTop()
- 파라미터로 전달받은 y축의 좌표값에 따라서, 값이 0보다 작은 경우 최상단이라고 판단합니다.
1.2. isAtBottom()
- 파라미터로 스크롤 뷰의 event.nativeEvent 값을 전달받아서 하단인지 여부를 판단합니다.
1.3. scroll()
- ScrollView의 동작(onScrollEndDrag)에 따라서 스크롤 드래그를 내렸을 때의 시점에 대한 이벤트 정보를 가져옵니다.
- 그리고, 최상단(isAtTop), 중간, 최하단(isAtBottom) 영역에 대한 계산을 함수를 호출하여서 여부를 판단하여 출력하고자 하는 View 영역에 대해 display 속성을 통해서 보임(display) 혹은 안 보임(none)을 수행합니다.
- 결론적으로 최상단일 경우는 최상단의 영역만 보이게 하고, 중간 영역인 경우 최상단, 최하단 영역을 안 보이게 하고, 하단 영역인 경우 최하단 영역만 보이게 합니다.
import React, { useRef } from "react"
import { NativeScrollEvent, NativeSyntheticEvent, Text, View } from "react-native"
import { ScrollView } from "react-native-gesture-handler";
const TestScreen = ({ navigation, route }) => {
const topAreaRef = useRef<View>(null); // 최상단의 영역을 가리킵니다.
const bottomAreaRef = useRef<View>(null); // 최하단의 영역을 가리킵니다.
/**
* ScrollView의 이벤트를 관리합니다.
*/
const handlerScrollView = (() => {
return {
/**
* 좌표값에 따라 최상위 여부를 반환 받습니다.
* @param {number} offsetY
* @returns {boolean} : 최상위 여부 반환
*/
isAtTop: (offsetY: number): boolean => offsetY <= 0,
/**
* 좌표값에 따라 최하단 여부를 반환 받습니다.
* @param {NativeSyntheticEvent<NativeScrollEvent>} event
* @returns {boolean} : 최하단 여부 반환
*/
isAtBottom: (event: NativeSyntheticEvent<NativeScrollEvent>): boolean => {
const { layoutMeasurement, contentOffset, contentSize } = event.nativeEvent;
const paddingToBottom = 20; // 원하는 여유 공간을 설정할 수 있습니다.
return layoutMeasurement.height + contentOffset.y >= contentSize.height - paddingToBottom;
},
/**
* 스크롤이 최상위나 최하단일 때 로그를 출력합니다.
* @param event
*/
scroll: (event: NativeSyntheticEvent<NativeScrollEvent>) => {
const offsetY = event.nativeEvent.contentOffset.y;
// [CASE3] 스크롤이 최상단에 위치한 경우
if (handlerScrollView.isAtTop(offsetY)) {
console.log('스크롤이 최상단입니다.');
topAreaRef.current!.setNativeProps({ style: { display: 'display' } }); // 최상단 화면 보임
bottomAreaRef.current!.setNativeProps({ style: { display: 'none' } }); // 최하단 화면 안보임
}
// [CASE2] 스크롤이 최하단에 위치한 경우
else if (handlerScrollView.isAtBottom(event)) {
console.log('스크롤이 최하단입니다.');
topAreaRef.current!.setNativeProps({ style: { display: 'none' } }); // 최상단 화면 안보임
bottomAreaRef.current!.setNativeProps({ style: { display: 'display' } }); // 최하단 화면 보임
}
// [CASE3] 스크롤이 중간 위치한 경우
else {
console.log('스크롤이 중간 위치입니다.');
topAreaRef.current!.setNativeProps({ style: { display: 'none' } }); // 최상단 화면 안보임
bottomAreaRef.current!.setNativeProps({ style: { display: 'none' } }); // 최하단 화면 안보임
}
},
}
})();
return (
<>
<View style={{ height: "100%" }}>
<View
ref={topAreaRef}
style={{ width: "100%", height: 50, backgroundColor: "#616d82" }}
>
<Text style={{ textAlign: "center", fontWeight: "bold" }}>최상단의 영역 일 경우 해당 화면이 나옵니다~</Text>
</View>
<ScrollView
onScrollEndDrag={(e) => handlerScrollView.scroll(e)}
scrollEventThrottle={10}
>
<Text style={{ marginBottom: 150 }}>
<Text style={{ fontSize: 20 }}>작은 토끼와 큰 당근 {"\\n"}</Text>
옛날 옛적에 작은 토끼 한 마리가 살았어요. 이 토끼는 당근을 아주 좋아했답니다.{"\\n"}
어느 날, 토끼는 정원에서 엄청나게 큰 당근을 발견했어요. 그 당근은 토끼보다 두 배나 컸죠!{"\\n"}
"와! 이렇게 큰 당근은 처음 봐요!" 토끼가 말했어요.{"\\n"}
토끼는 그 큰 당근을 집으로 가져가고 싶었지만, 너무 무거워서 혼자서는 들 수 없었어요.{"\\n"}
그때 친구들이 나타났어요. 다람쥐, 두더지, 그리고 생쥐였죠.{"\\n"}
"우리가 도와줄게!" 친구들이 말했어요.{"\\n"}
모두 함께 힘을 모아 당근을 들어올렸어요. 그리고 토끼의 집으로 가져갔답니다.{"\\n"}
토끼는 친구들과 함께 맛있는 당근 요리를 만들어 나눠 먹었어요.{"\\n"}
"혼자서는 할 수 없었지만, 친구들과 함께라면 무엇이든 할 수 있어요!" 토끼가 행복하게 말했답니다.{"\\n"}
그 후로 토끼와 친구들은 더욱 사이좋게 지냈답니다. 끝.
</Text>
<Text>
<Text style={{ fontSize: 20 }}>황금 물고기의 소원{"\\n"}</Text>
옛날 옛적에 가난한 어부가 살았어요. 그는 매일 바다에 나가 물고기를 잡았답니다.{"\\n"}
어느 날, 어부는 반짝이는 황금 물고기를 잡았어요. 그런데 놀랍게도 그 물고기가 말을 했어요!{"\\n"}
"제발 나를 놓아주세요. 그러면 당신의 소원을 세 가지 들어드릴게요."{"\\n"}
어부는 깜짝 놀랐지만, 물고기를 놓아주었어요.{"\\n"}
"첫 번째 소원은 무엇인가요?" 물고기가 물었어요.{"\\n"}
"우리 집이 좀 더 크고 편안했으면 좋겠어요." 어부가 말했어요.{"\\n"}
순식간에 어부의 집은 아름다운 저택으로 변했어요.{"\\n"}
"두 번째 소원은요?" 물고기가 다시 물었어요.{"\\n"}
"풍요로운 정원이 있었으면 좋겠어요." 어부가 대답했어요.{"\\n"}
그러자 저택 주변에 아름다운 정원이 생겼어요.{"\\n"}
"마지막 소원은 무엇인가요?" 물고기가 물었어요.{"\\n"}
어부는 잠시 생각하다가 말했어요. "더 이상 바라는 게 없어요. 지금 이대로 행복합니다."{"\\n"}
황금 물고기는 미소 지으며 말했어요. "당신의 만족하는 마음이 가장 큰 행복의 비결이에요."{"\\n"}
그 후로 어부는 가족과 함께 행복하게 살았답니다. 끝.{"\\n"}
</Text>
</ScrollView>
<View
ref={bottomAreaRef}
style={{ width: "100%", height: 50, backgroundColor: "#3f4855", display: "none" }}
>
<Text style={{ textAlign: "center", fontWeight: "bold" }}>최하단 영역 일 경우 해당 화면이 나옵니다~</Text>
</View>
</View>
</>
)
}
export default TestScreen
3) 최상단/최하단으로 이동 시 특정 영역이 출력되는 활용예시 결과
💡최상단/최하단으로 이동 시 특정 영역이 출력되는 활용예시 결과
- 아래와 같은 결과로 순차적으로 최상단으로 내릴 때는 최상단 영역이 나오고 중간 영역으로 내릴 때는 최상단, 최하단 영역이 보이지 않고, 최하단으로 내릴 때는 최하단 영역만 보입니다.
오늘도 감사합니다. 😀
반응형
'React & React Native > Short 개발' 카테고리의 다른 글
[RN/Short] React Native Android / iOS 앱 이름 바꾸기 (0) | 2024.09.10 |
---|---|
[RN/Short] React Native 자주 사용하는 명령어 package.json scripts로 구성하기 : Run, Build (2) | 2024.09.10 |
[RN/Short] React Native TextInput 입력 시 최초 키보드 타입 지정 방법: 대문자, 소문자, 숫자 (0) | 2024.09.06 |
[RN/Short] React Native 디바이스 별 폰트 사이즈 고정 설정 방법 : Text, TextInput (0) | 2024.09.06 |
[RN/Short] React Native Modal 뒷 배경 반투명 처리 방법 : centeredView (0) | 2024.09.06 |