본문 바로가기
Android

[Doit 깡샘의 안드로이드 앱 프로그래밍 with 코틀린] 정리 12 - 탭 레이아웃 ― 탭 버튼 구성

by 들풀민들레 2022. 2. 28.
본 글은 [Doit 깡샘의 안드로이드 앱 프로그래밍 with 코틀린 - 이지스퍼블리싱 (2022)] 의 내용을 발췌한 것입니다.

좀더 자세한 내용은 책 혹은 인강을 통해 확인해 주세요.

 

 

 

탭 레이아웃은 탭tab으로 구분하는 화면에서 탭 버튼을 배치하는 레이아웃입니다. 탭 화면에는 탭 버튼을 선택했을 때 나와야 하는 내용이 있습니다. 탭 레이아웃은 이 중 탭 버튼을 다양하게 표시하고자 사용하는 뷰입니다.
다음 그림은 Play 스토어 앱의 화면입니다. 상자로 표시한 부분에 탭 버튼이 사용되었습니다.

 

왼쪽 그림에서 위의 탭 버튼은 가로로 스크롤됩니다. 탭 버튼이 많으면 이처럼 스크롤되게 제공해야 합니다. 왼쪽 그림에서 아래의 탭 버튼은 4개를 가로 등분으로 제공합니다. 그리고 오른쪽 그림에서 위의 탭 버튼은 왼쪽으로 정렬되었습니다. 이처럼 탭 버튼을 어떻게 출력할 것인지 탭 레이아웃을 이용해 설정할 수 있습니다.

 

<LinearLayout xmlns:android=”http://schemas.android.com/apk/res/android”
    android:layout_width=”match_parent”
    android:layout_height=”match_parent”
    android:orientation=”vertical”>
    <com.google.android.material.tabs.TabLayout
        android:id=”@+id/tabs”
        android:layout_width=”match_parent”
        android:layout_height=”wrap_content” />
    <FrameLayout
        android:id=”@+id/tabContent”
        android:layout_width=”match_parent”
        android:layout_height=”match_parent” />
</LinearLayout>

위 코드는 탭 화면을 만드는 레이아웃 XML 파일입니다. TabLayout과 FrameLayout을 선언했습니다. 사용자가 TabLayout으로 구성한 탭 버튼을 선택하면 FrameLayout 위치에 탭의 내용을 출력합니다.

 

val tab1: TabLayout.Tab = tabLayout.newTab()
tab1.text=”Tab1”
tabLayout.addTab(tab1)

val tab2: TabLayout.Tab = tabLayout.newTab()
tab2.text=”Tab2”
tabLayout.addTab(tab2)

val tab3: TabLayout.Tab = tabLayout.newTab()
tab3.text=”Tab3”
tabLayout.addTab(tab3)

탭 레이아웃에 추가되는 탭 버튼은 TabLayout.newTab() 함수로 만들어지는 TabLayout.Tab 객체이며 이 객체의 text 속성으로 문자열을, icon 속성으로 이미지를 지정합니다. 그리고 이 Tab 객체를 TabLayout.addTab() 함수의 매개변수로 지정하여 탭 버튼을 추가합니다.

 

위 코드는 TabLayout에 Tab 객체를 3개 추가했으므로 탭 버튼이 3개인 탭 화면을 만듭니다. 그런데 만약 탭 레이아웃의 탭 버튼을 동적으로 만들 필요가 없다면 앞의 예처럼 탭 버튼을 코드에서 정의하지 않고 레이아웃 XML 파일의 TabItem으로 정의해도 됩니다. TabLayout 하위에 추가되는 TabItem 하나가 탭 버튼 하나를 의미합니다.

 

<com.google.android.material.tabs.TabLayout
    android:id=”@+id/tabs”
    android:layout_width=”match_parent”
    android:layout_height=”wrap_content”>
    <com.google.android.material.tabs.TabItem
        android:layout_width=”wrap_content”
        android:layout_height=”wrap_content”
        android:text=”Tab1” />
    <com.google.android.material.tabs.TabItem
        android:layout_width=”wrap_content”
        android:layout_height=”wrap_content”
        android:text=”Tab2” />
    <com.google.android.material.tabs.TabItem
        android:layout_width=”wrap_content”
        android:layout_height=”wrap_content”
        android:text=”Tab3” />
</com.google.android.material.tabs.TabLayout>

사용자가 탭 버튼을 선택할 때 출력해야 하는 내용은 코드에서 탭 버튼의 이벤트 핸들러에 명시해야 합니다.

 

tabLayout.addOnTabSelectedListener(object: TabLayout.OnTabSelectedListener {
    // 탭 버튼을 선택할 때 이벤트
    override fun onTabSelected(tab: TabLayout.Tab?) {
        val transaction = supportFragmentManager.beginTransaction()
        when (tab?.text) {
            “Tab1”-> transaction.replace(R.id.tabContent, OneFragment())
            “Tab2”-> transaction.replace(R.id.tabContent, TwoFragment())
            “Tab3”-> transaction.replace(R.id.tabContent, ThreeFragment())
        }
        transaction.commit()
    }
    // 선택된 탭 버튼을 다시 선택할 때 이벤트
    override fun onTabReselected(tab: TabLayout.Tab?) {
    	(... 생략 ...)
    }
    // 다른 탭 버튼을 눌러 선택된 탭 버튼이 해제될 때 이벤트
    override fun onTabUnselected(tab: TabLayout.Tab?) {
    	(... 생략 ...)
    }
})

TabLayout을 이용해 탭 버튼 3개를 출력한 예입니다. 탭 레이아웃은 기본으로 탭 버튼을 가로 등분으로 배치합니다. 그러므로 3개의 버튼이 가로 3등분으로 출력되었습니다.
TabLayout의 addOnTabSelectedListener() 함수를 이용해 이벤트 핸들러 객체를 지정해 줍니다. 탭 버튼 이벤트 핸들러 객체는 TabLayout.OnTabSelectedListener를 구현한 객체여야 하며 각 이벤트 콜백 함수의 매개변수는 현재 이벤트가 발생한 Tab 객체입니다.
탭 레이아웃은 다음과 같은 속성으로 탭 버튼을 다양하게 출력할 수 있습니다.


탭 버튼 정렬하기


tabGravity는 탭 버튼을 정렬하는 속성입니다. 기본값은 fill이며 탭 버튼을 가로로 등분하여 배치합니다. center는 탭 버튼을 가운데 정렬합니다.

 

스크롤 설정하기


tabMode 속성은 탭 버튼을 스크롤할 수 있는지를 설정합니다. 기본값은 fixed인데 스크롤을 지원하지 않는다는 의미입니다. 만약 scrollable로 설정하면 탭 버튼이 왼쪽부터 나열되고 모두 출력할 수 없다면 자동으로 가로 스크롤이 생깁니다.

 

 

뷰 페이저 연동하기


탭 레이아웃으로 탭 화면을 만들면서 11장에서 살펴본 뷰 페이저와 연동할 수 있습니다. 탭 레이아웃과 뷰 페이저는 화면을 여러 장 제공하는 용도이므로 둘을 연동하는 일이 많습니다. 예를 들어 오른쪽 그림은 Facebook 앱의 화면입니다.

 

화면 위쪽을 보면 탭 버튼이 6개 보입니다. 탭 버튼을 눌러 화면을 전환할 수 있지만, 탭 버튼 아래 콘텐츠 부분을 뷰 페이저로 제공하여 스와이프로 화면을 전환하게 할 수도 있습니다. 이처럼 탭 레이아웃은 뷰 페이저와 연동을 지원합니다.

 

<LinearLayout xmlns:android=”http://schemas.android.com/apk/res/android”
    android:layout_width=”match_parent”
    android:layout_height=”match_parent”
    xmlns:app=”http://schemas.android.com/apk/res-auto”
    android:orientation=”vertical”>
    <com.google.android.material.tabs.TabLayout
        android:id=”@+id/tabs”
        android:layout_width=”match_parent”
        android:layout_height=”wrap_content”
        app:tabMode=”scrollable”>
    </com.google.android.material.tabs.TabLayout>
    <androidx.viewpager2.widget.ViewPager2
        android:id=”@+id/viewpager”
        android:layout_width=”match_parent”
        android:layout_height=”match_parent” />
</LinearLayout>

레이아웃 XML 파일에 TabLayout과 ViewPager2를 등록한 후 코드에서 TabLayoutMediator를 이용해 둘을 연동하면 됩니다.

TabLayoutMediator(tabLayout, viewPager) { tab, position ->
	tab.text = “Tab${(position + 1)}”
}.attach()

TabLayoutMediator 생성자의 매개변수로 연동하고자 하는 탭 레이아웃과 뷰 페이저 객체를 전달합니다. 이렇게 하면 뷰 페이저의 화면이 3개이면 탭 버튼도 자동으로 3개가 나옵니다.
또한 사용자가 탭 버튼을 누르는 순간 뷰 페이저 화면이 자동으로 조정되며, 반대로 사용자가 뷰 페이저 화면을 넘기는 순간 탭 버튼도 자동으로 조정됩니다. 이처럼 뷰 페이저와 연동하면 탭 버튼의 문자열은 3번째 매개변수로 전달하는 함수에서 지정할 수 있습니다. 이 함수의 매개변수는 탭 버튼 객체(tab)와 화면에서 위치(position)이므로 이를 이용해 탭 버튼의 문자열 등을 지정하면 됩니다.