안드로이드 공부/ TabLayout, Pager

TabLayout과 Pager

TabLayout

  • 'tab'들을 담당하는 역할

Pager

  • 화면 양옆으로 밀어서 넘기는 역할

Adapter

  • TableLayout과 Pager를 연결해주는 역할

📎 TabLayout과 Pager 예제

1. xml 파일에 TabLayout과 ViewPager 생성

1-1. 의존성 추가

Tablayout은 기본적으로 제공되지 않기 때문에 라이브러리를 가져와야 한다.

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

1-2. xml 파일 작성하기

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".TabPagerActivity"
    android:orientation="vertical">

    <!-- TabLayout -->
    <com.google.android.material.tabs.TabLayout
        android:id="@+id/tab_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        />

    <!-- ViewPager -->
    <androidx.viewpager.widget.ViewPager
        android:id="@+id/view_pager"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        />

</LinearLayout>

2. PagerAdapter 생성하기

  • 소수의 프래그먼트로 페이징하는 경우에는 PagerStatePagerAdapter 인터페이스를 implement한다.
    (뷰를 통해 페이징: RecyclerView.Adapter
    수많은 프래그먼트로 페이징: PagerStateAdapter)
class PagerAdapter(
    fragmentManager: FragmentManager,
    val tabCount: Int
): PagerStatePagerAdapter(fragmentManager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT){

    // tab들의 개수를 리턴
    override fun getCount(): Int {
        return tabCount
    }

    // position에 따른 fragment를 리턴해준다.
    override fun getItem(position: Int): Fragment {
        return when(position){
            0 -> {
                FragmentFirst()
            }
            1 -> {
                FragmentSecond()
            }
            2 -> {
                FragmentThird()
            }
            else -> {
                FragmentFirst()
            }
        }
    }
}

BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT

  • 현재 프래그먼트만 RESUMED 상태에 있고, 나머지 프래그먼트들은 STARTED 상태에 남아있는다.

3. Tablayout 만들기

  • tablayout에 새로 Tab을 만들어서 붙인다.
val tabLayout: TabLayout = findViewById(R.id.tab_layout)

tabLayout.addTab(tabLayout.newTab().setText("One"))
tabLayout.addTab(tabLayout.newTab().setText("Two"))
tabLayout.addTab(tabLayout.newTab().setText("Three"))
  • 실행 결과

4. Pager 만들기

  • PagerAdapter와 ViewPager를 만들어서 ViewPager의 어댑터에 만든 PagerAdapter 넘겨주기
val pagerAdapter = PagerAdapter(supportFragmentManager, 3)
val viewPager: ViewPager = findViewById(R.id.view_pager)
viewPager.adapter = pagerAdapter

5. TabLayout과 Pager 연결하기(동기화)

5-1. tab을 클릭하면 page가 넘어가도록

tabLayout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener{

    // tab이 클릭되면 viewPager의 현재 아이템을 변경
    override fun onTabSelected(tab: TabLayout.Tab?) {
        viewPager.currentItem = tab!!.position
    }

            
   // override fun onTabUnselected(tab: TabLayout.Tab?) {

   //}

   // override fun onTabReselected(tab: TabLayout.Tab?) {

   //}
})

5-2. page를 넘기면 tab도 같이 넘어가도록

// page가 바뀌면 tabLayout도 변하도록
viewPager.addOnPageChangeListener(TabLayout.TabLayoutOnPageChangeListener(tabLayout))

실행 화면


📎 fragment 없이 viewPager 만들기

  • fragment를 변환해주는 게 아니라 직접 xml을 inflate해서 page가 넘어갈 때마다 view를 그려주는 방식이다.
  • Adapter만 변경해주면 된다.
class ThreePagerAdapter(
    val layoutInflater: LayoutInflater
): PagerAdapter(){

    // 뷰를 그려주는 부분
    override fun instantiateItem(container: ViewGroup, position: Int): Any {
        when(position){
            0 -> {
                val view = layoutInflater.inflate(R.layout.fragment1,container, false)
                container.addView(view)
                return view // 이게 나중에 파라미터로 전달되는 `object`
            }
            1 -> {
                val view = layoutInflater.inflate(R.layout.fragment2,container, false)
                container.addView(view)
                return view 
            }
            2 -> {
                val view = layoutInflater.inflate(R.layout.fragment3,container, false)
                container.addView(view)
                return view 
            }
            else -> {
                val view = layoutInflater.inflate(R.layout.fragment1,container, false)
                container.addView(view)
                return view 
            }
        }
    }

    // 해당 view가 가려질 때 호출된다.
    override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) {
        // container에서 아이템 떼어내기
        container.removeView(`object` as View)
    }

    // viewPager에 있는 page 개수
    override fun getCount(): Int {
        return 3
    }

    // 여기서 view는 현재 보고있는 view가 현재 원하는 view가 (`object`)가 맞는지 확인
    override fun isViewFromObject(view: View, `object`: Any): Boolean {
       return view === `object` as View
    }
}

좋은 웹페이지 즐겨찾기