Application/React Native

[ React Native ] FlatList + slide card

Yume Dev 2025. 10. 15. 01:15
반응형

grid layout을 할려고 style을 적용해보는데 react native에는 flex: grid가 없어서 찾아보다가

그리드 기능을 해주는 flatList를 이용


Useage

flatList는 가로 세로 두가지를 할 수 있으며 각각 사용법이 다르다.

 

1. vertical

우선 flaticon에서 해당 월의 개수만큼 박스를 만들려고해서

해당 월의 마지막날을 data로 넣어주었다.

 

numColums는 한 줄에 몇개를 할지 설정할 수 있다.

이후 박스 영역 안에 넣어줘야하므로 onLayout을 이용해 박스 영역의 크기를 계산하여 박스 영역 안에 들어가는 item 박스의 크기를 계산

 

columWrapperStyle로 각 아이템의 간격을 설정

이후 renderItem으로 아이템 박스를 생성

const GAP = 4; 
const numColumns = 10;
const itemWidth = boxWidth
        ? Math.floor((boxWidth - GAP * (numColumns - 1) - 25) / numColumns)
        : 0;
<BoxView
            onLayout={(e) => {
            const { width } = e.nativeEvent.layout;
            setBoxWidth(width);
        }}>
            <BetweenView style={styles.btwSpace}>
                <AppText>{prop.title}</AppText>
                <SvgIcon name='Dot' fill/>
            </BetweenView>
            <View style={styles.metricContainer}>
                <FlatList
                    data={Array.from({ length: daysInMonth }, (_, i) => i)}
                    keyExtractor={(item) => item.toString()}
                    numColumns={numColumns}
                    columnWrapperStyle={{ gap: GAP }}
                    renderItem={() =>
                        <View style={[styles.metric, {
                            width: itemWidth,
                            height: itemWidth,
                        }]} />
                }
                />
            </View>
        </BoxView>

 

그럼 한줄에 10개인 아이템 박스가 4줄로 나오게 된다.

여기서 style로 flex: row 를 활용하지 않고 flatList를 사용한 이유는 flex:row를 사용하다보면 양끝의 빈 공간이 문제가 생겨서 flatList를 활용했다.

 


1. horizontal

그럼 이제 위에 만든 박스를 여러개 만들어서 slide를 적용해서 움직일 수 있게 구현

slide도 flatList를 활용하면 쉽게 구현할 수 있다.

 

사용방법은 vertical과 비슷하다

horizontal속성을 넣어주고

showsHorizontalScrollIndicator={false}

  • UI를 깔끔하게 보이게 할 때 사용
  • 가로 스크롤을 숨겨준다.

decelerationRate="fast"

  • 스크롤 감속 속도를 제어
  • "normal" : 기본 속도
  • "fast" : 손을 놓았을 때 더 빨리 멈춤 → 스냅 느낌 강화

snapToInterval={ITEM_WIDTH + ITEM_SPACING}

  • 스냅 단위 거리 지정
  • FlatList가 스크롤 끝에 멈출 때 얼마만큼 이동할지 결정
  • 여기서는 “카드 하나 + 오른쪽 간격” 만큼 스크롤 → 한 번에 한 카드 단위로 멈춤

snapToAlignment="start"

  • 스냅 위치를 시작점(왼쪽) 기준으로 맞춤
  • "center" : 스냅 위치를 카드 중앙 기준
  • "end" : 카드 오른쪽 기준
const metrics = [
        { id: 1, component: <MetricItem title="metric 1"/>},
        { id: 2, component: <MetricItem title="metric 2"/>},
        { id: 3, component: <MetricItem title="metric 3"/>},
    ]
return (
        <View>
            <BetweenView style={styles.btwSpace}>
                <AppText>( {metrics.length} )</AppText>
                <SvgIcon name='Dot' fill/>
            </BetweenView>
            <FlatList
                data={metrics}
                horizontal
                showsHorizontalScrollIndicator={false}
                decelerationRate="fast"
                snapToInterval={ITEM_WIDTH + ITEM_SPACING} 
                snapToAlignment="start"
                keyExtractor={item => item.id.toString()}
                renderItem={({item,index}) => (
                    <View style={{width: ITEM_WIDTH,
                        marginRight: index === metrics.length - 1 ? 0 : ITEM_SPACING, }}>
                        {item.component}
                    </View>
                )}
            />
        </View>
    )

 

그럼 스크롤하면 자연스럽게 스크롤이 되는것을 확인할 수 있다.

728x90
반응형