Pa K'ode

[안드로이드] TabLayout, ViewPager2 사용법과 다양한 활용방법 본문

안드로이드

[안드로이드] TabLayout, ViewPager2 사용법과 다양한 활용방법

Paku 2021. 12. 30. 12:01

안녕하세요! 주니어 개발자 파쿠입니다 ;)

 

이번 포스팅은 구글에서 제공하는 Tablayout 에 대해 적어보려고 합니다.

겸사겸사 Tablayout 과 절친한 ViewPager2 에 대해서도 함께 알아보겠습니다.

ViewPager 는 1,2 두가지 버전이 존재하며 해당 포스팅에서 다룰건 ViewPager2입니다.

 

안드로이드 앱을 개발하다보면 한 페이지에 이렇게

 

이동 가능 한 여러가지의 탭이 들어가야하는 UI가 필요할 떄가 있는데요, Tablayout 은 이런 디자인에 최적화되어있습니다.

 

이런식으로 하단에 Indicator 역활도 할수있는 아주 유용한 친구입니다.

 

0) Gradle에 Library 추가하기

 

역시 가장 먼저 해야하는 작업은 스튜디오에 Library를 추가해 줘야 하는데요,

app 수준의 gradle 파일에 dependency 내에 아래 라이브러리를 추가해 줍니다.

 

implementation 'com.google.android.material:material:1.4.0'

 

API 29(Q) 이상의 버전부터는 support 라이브러리에서 material 라이브러리로 변경되었습니다

 

동기화 까지 하셨다면, 다음 단계로 넘어가도록 하겠습니다.

 

1) Layout 그려주기

 

xml 파일을 만들어 줍니다.

.XML

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/white">

        <include
            android:id="@+id/layout_toolbar"
            layout="@layout/layout_detail_header"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:title="@{`이벤트`}" />

        <com.google.android.material.tabs.TabLayout
            android:id="@+id/tab"
            android:layout_width="match_parent"
            android:layout_height="56dp"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/layout_toolbar"
            style="@style/TabStyle"/>
       
        <androidx.viewpager2.widget.ViewPager2
            android:id="@+id/viewPager"
            android:layout_width="0dp"
            android:layout_height="0dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/tab_container" />
            
    </androidx.constraintlayout.widget.ConstraintLayout>

 

하단의 ViewPager2 는 각자의 탭에 맞는 뷰가 그려질 파트입니다. 

꼭 ViewPager를 사용하지 않으셔도 됩니다. 다른 Layout으로 대체할수도 있습니다. 예) FrameLayout 등

 

이곳에서 Tablayout 의 디자인을 설정해 줘야 하는데요, 하나씩 알아보도록 하겠습니다

res > values > style.xml 파일에 들어가줍니다. 해당 파일이 없다면 thems.xml 또는 파일을 만들어주세요.

 

style.xml

<style name="TabLayout" parent="Widget.Design.TabLayout">
    <item name="tabPaddingBottom">15dp</item>
    <item name="tabGravity">fill</item>
    <item name="tabIndicatorColor">@color/colorPrimary</item>
    <item name="tabIndicatorFullWidth">true</item>
    <item name="tabBackground">@drawable/tab_indicator_line</item>
    <item name="tabIndicatorGravity">bottom</item>
    <item name="tabMode">fixed</item>
    <item name="tabSelectedTextColor">@color/colorBlack</item>
    <item name="tabTextAppearance">@style/GuideUnselectedTabText</item>
</style>

<style name="GuideUnselectedTabText" parent="TextAppearance.Design.Tab">
    <item name="android:includeFontPadding">false</item>
    <item name="android:textSize">14sp</item>
    <item name="android:textColor">@color/light_pale_grey</item>
    <item name="android:lineSpacingExtra">7sp</item>
    <item name="textAllCaps">false</item>
    <item name="android:textAllCaps">false</item>
    <item name="android:textStyle">bold</item>
</style>

 

여기서 중요하게 설정해야 할 파트만 집고 넘어가도록 하겠습니다.

 

tabGravity : TabLayout 내 탭들의 위치를 설정합니다.

  • fill: 전체 레이아웃에 크기에 맞춰서 탭들의 위치가 일정하게 조정됩니다.
  • center : 가운데 정렬입니다.
  • start: 시작점으로 부터 좌측 정렬됩니다.

 

tabMode: 탭들의 처리 방식을 설정합니다. 너무 많은 탭들이 있을떄 유효합니다.

  • fixed: 한 화면의 모든 탭들을 보여줍니다.
  • srollable: 좌/우 스크롤이 가능하게 보여줍니다.
  • auto: 자동으로 설정합니다.

tabIndicatorColor: 선택된 탭 구분선의 색상을 설정합니다..

tabIndicatorFullWidth: 구분선의 가로 크기를 'match parent' 로 설정합니다

tabBackground: 각 탭들의 바탕이될 화면을 설정합니다.

tabSelectedTextColor: 선택된 탭의 글자를 설정합니다

 

2) ViewPager2에 들어갈 아이템 추가하기 

 

이제 ViewPager2 내에 들어갈 아이템들을 만들어 주도록 하겠습니다. 아이템 내엔 어떤 뷰가 와도 상관없습니다.

해당 예제에선 ViewPager2 내에 Fragment 들을 넣어주도록 하겠습니다.

 

Adapter.class

class EventTypePagerAdapter : FragmentStateAdapter, TabLayoutMediator.TabConfigurationStrategy {
    private val fragmentLaunchers: List<() -> Fragment> = listOf(
        { 생성한 프래그먼트 1 },
        { 생성한 프래그먼트 2 }
    )
    private val titles = listOf(
        "진행중 이벤트",
        "종료된 이벤트"
    )

    constructor(fragmentActivity: FragmentActivity) : super(fragmentActivity)
    constructor(fragment: Fragment) : super(fragment)
    constructor(fragmentManager: FragmentManager, lifecycle: Lifecycle) : super(
        fragmentManager,
        lifecycle
    )

    override fun onConfigureTab(tab: TabLayout.Tab, position: Int) {
        tab.text = titles[position]
    }

    override fun getItemCount() = fragmentLaunchers.size

    override fun createFragment(position: Int): Fragment {
        return fragmentLaunchers[position].invoke()
    }
}

생성한 fragment 를 리스트로 담아서 관리하고, 탭의 포지션이 변경될떄마다 fragment와 title이 변경되는 구조입니다.

 

여기까지 완료하셨다면 마무리 단계입니다.

 

3) Tablayout, ViewPager2 결합하기

 

1번 과정 에서 생성한 xml을 관리하는 Activity/Fragment 로 들어와 줍니다.

 

Fragment.class

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    
    val adapter = EventTypePagerAdapter(childFragmentManager, lifecycle)
    
    with(viewDataBinding) {
        layoutToolbar.btnBack.setOnClickListener {
            navController.popBackStack()
        }

        with(viewPager) {
            this.adapter = adapter
        }

        TabLayoutMediator(
            tab,
            viewPager,
            true,
            true,
            adapter
        ).attach()
    }
}
viewdatabiding 설정이 되어있어야 합니다.

 

TabLayoutMediator 내에 순서대로

  1.  1번과정에서 생성한 TabLayout의 id
  2.  마찬가지로 ViewPager2의 id
  3. autoRefresh 설정
  4. smoothSrcoll 설정
  5. tabConfigurationStrategy = 2번과정에서 생성한 어뎁터입니다.

 

여기까지 잘 따라오셨다면 끝입니다!  한번 결과물을 볼까요?

 

 

아주 만족스럽게 결과물이 나왔습니다!

 

 

여기까지 본 포스팅 마치도록 하겠습니다 :)

저는 다음 포스팅으로 찾아뵙겠습니다 감사합니다.

Comments