본문 바로가기
안드로이드 공부 노트/Compose(컴포즈)

[Android-Compose] Compose 스와이프 가능한 탭 UI 만들기 - 1편TabRow

by 지게요 2025. 11. 11.
728x90
반응형

오늘의 공부노트는 프로젝트에 많이 사용되는 스와이프 탭 UI 만드는 법을 적어보겠다!

우선 TabRow, HorizontalPager 각각 컴포넌트를 알아야 할 수 있기 때문에 먼저 각 컴포넌트를 알아보자.

본 예제는 Material Design3을 따른다.

# TabRow

-  여러 개의 Tab을 가로로 배치하고, 현재 선택된 탭을 시각적으로 표시하는 컴포넌트

@Composable
@UiComposable
fun TabRow(
    selectedTabIndex: Int,
    modifier: Modifier = Modifier,
    backgroundColor: Color = MaterialTheme.colors.primarySurface,
    contentColor: Color = contentColorFor(backgroundColor),
    indicator: @Composable @UiComposable
        (tabPositions: List<TabPosition>) -> Unit = @Composable { tabPositions ->
            TabRowDefaults.Indicator(
                Modifier.tabIndicatorOffset(tabPositions[selectedTabIndex])
            )
        },
    divider: @Composable @UiComposable () -> Unit =
        @Composable {
            TabRowDefaults.Divider()
        },
    tabs: @Composable @UiComposable () -> Unit
)

위 코드는 TabRow의 파라미터들이다. 중요 파라미터를 알아보자!

🟢 selectedTabIndex: 필수. 현재 선택된 탭의 인덱스를 나타낸다.

🟢 contentColor: 선택. 콘텐츠의 색을 결정한다.

- 해당 콘텐츠 색상을 Red로 변경 시 아래 사진과 같이 변경

contentColor = Color.Red

 

🟢 backgroundColor: 선택. 배경 색을 결정한다.

- 해당 배경색을 White로 변경 시 아래 사진과 같이 변경

backgroundColor = Color.White,

 

🟢 indicator: 선택. 선택 표시줄을 원하는 스타일로 바꿀 때 사용

indicator: 선택된 탭 아래에 그려지는 시각적 포인터이다. 즉, 사용자가 "지금 어떤 탭이 선택되어 있는지" 한눈에 알아볼 수 있도록 해주는 시각적 장치이다. 
위 사진의 빨간 부분을 말한다.

 

🟢 divider: 선택. TabRow의 전체 너비에 걸쳐 표시되는 선을 바꿀 때 사용

divider = { HorizontalDivider(color = Color.Red) },

- 해당 divider 색을 빨강으로 변경 시 위 사진과 같이 변경

 

indicator와 차이점은 indicator는 현재 선택되어 있는 탭 아래에 표시되는 선을 나타내고 divider은 TabRow의 전체 너비에 걸쳐 표시되는 선을 나타낸다.

 

🟢 tabs: 필수. TabRow 내부에 표시할 탭들을 정의하는 영역

tabs = {
    repeat(4) { index ->
        // 커스텀 방식
        Text(text = "탭$index")
        
        // 제공하는 Tab 컴포저블을 이용하는 방식
        Tab(
            selected = selectTabIdx == index,
            onClick = { selectTabIdx = index},
            text = { Text(text = "탭$index") }
        )
    }
}

 

TabRow의 들어갈 Tab 들을 정의 할 수 있는 방법이 2가지가 있다.

1. 커스텀 방식

2. 안드로이드에서 기본적으로 제공하는 Tab 컴포저블을 이용하는 방식

 

## 커스텀 방식

탭의 디자인을 완전히 자유롭게 구성할 수 있는 방식이다.

Tab 컴포저블을 사용하지 않고 Box, Text, Icon 등 일반 컴포저블들을 조합하여 원하는 형태의 탭을 만들 수 있다.

 

해당 방식의 단점으로는

- 작업하는 프로젝트가 Material Design 가이드라인을 따른다면 적합하지 않다.

- 클릭 기능이나 선택 상태 등 직접 구현해야 할 일이 생긴다.

 

## Tab 컴포저블 방식

안드로이드에서 기본적으로 제공하는 Tab 컴포저블을 사용하는 방식이다. 선택 상태 관리, 접근성, 터치 피드백 등이 자동으로 처리된다.

@Composable
fun Tab(
    selected: Boolean,
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    text: @Composable (() -> Unit)? = null,
    icon: @Composable (() -> Unit)? = null,
    selectedContentColor: Color = LocalContentColor.current,
    unselectedContentColor: Color = selectedContentColor,
    interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }
) {
   ...
   ...
}

 

위는 Tab 컴포저블의 내부 구현이다.

보다시피 클릭 로직이나 활성, 선택 상태 등 이미 내부에서 구현을 해놨기 때문에 간편하다.

 

해당 방식의 단점으로는

- 내가 원하는 디자인을 사용할 수 없다는 디자인 커스터마이징에 제약이 있다.

 

                                                                                                            <커스텀 방식>

 

                                                                                                            <Tab 컴포저블 방식>

 

사진으로 보면 Tab 컴포저블 방식을 사용한 탭이 크기가 크다.

그 이유는 Tab 컴포저블 내부에서 Material 디자인 스펙과 텍스트 스타일(폰트 크기), 패딩 값에 따라 Tab 컴포저블 크기가 자동으로 계산되기 때문에 적절한 크기를 맞춰 준다.

 

‼️ 팁 Tab 컴포저블이지만 크기를 바꾸고 싶다면 Tab 컴포저블의 modifier를 사용하면 크기 변경이 가능하다.

 


공부하면서 느낀 점은 만약 TabRow 컴포저블의 존재를 몰랐다면 귀찮게 Row의 반복문을 작성해서 일일이 구현했을 것이다. UI 제작 전 해당 UI에 최적화된 컴포저블이 있는지 찾아보는 행위가 중요하다는 것을 느꼈다.

 

 

이렇게 1편으로 TabRow에 대해 알아봤다. 이제 2편에서는 해당 탭을 스와이프를 시켜주기 위한 HorizontalPager에 대해 알아볼 것이다.

 

반응형