[안드로이드]ViewPager2/ViewPager2와TabLayout연결

✅ViewPager2의 등장!!

ViewPager2 왜 등장함?

  • ViewPager2는 기존 ViewPager라이브러리에 몇가지 기능을 추가하여 출시된, 화면을 슬라이드하는 애니메이션이 구현되어있는 안드로이드 Jetpack컴포넌트임
  • 기존 ViewPager의 불편한 점을 개선하고 좀더 다양한 슬라이드 애니메이션 기능이 있는 ViewPager2를 출시한것이며 ViewPager는 더 이상 유지 보수 하지 않을 거라 함

ViewPager2 뭐가 더 좋음?

  • 1.세로 방향 지원:ViewPager는 가로 방향 슬라이드만 지원했지만 ViewPager2는 세로방향 슬라이드 애니메이션도 지원
  • 2.TabLayout과 연동시킬 경우 오른쪽에서 왼쪽으로 증가하는 모션 추가
  • 3.수정 가능한 Fragment Collection 지원
    ViewPager2는 수정 가능한 Fragment Collection 기능을 통해 페이징을 지원하며 기본 Collection이 변경되면 notifyDatasetChanged() 를 호출하여 UI를 업데이트 해준다.
  • 4.DiffUtil
    ViewPager2는 RecyclerView 를 기반으로 빌드되므로 DiffUtil이라는 유틸리티 클래스에 엑세스할 수 있다.
    따라서 ViewPager2 객체는 RecyclerView 클래스의 notifyDatasetChanged()를 활용할 수 있다.

✅ViewPager2 사용

1.종속성 추가

  • ViewPager2는 Jetpack 컴포넌트이므로 사용하기 위해 프로젝트에 종속성 추가를 해줘야함

2.화면 구성될 Fragment,xml 만들기

  • 각각의 ViewPager를 구성할 Fragment를 3개 만들어줄 것(더 만들어줘도 당연 됨)
  • Fragment를 만들었으면, Fragment의 onCreateView 메소드에서 inflate될 xml파일을 Fragment별로 각각 하나씩 총 3개 만듦

3.메인 엑티비티에 ViewPager2 뷰 추가

4.메인 엑티비티에 Adapter만들기

  • ViewPager2는 내장되어 있는 슬라이드 기능을 통해 새로운 페이지를 보여줌

  • 이 과정에서 새로운 페이지를 보여주기 위한 작업을 담당하는 것이 FragmentStateAdapter

  • FragmentStateAdapterAdapter 클래스를 상속받고 있는데 이 Adapter클래스는 RecyclerView의 Adapter만들때도 RecyclerView.Adapter를 상속받아 만들었을때의 Adapter와 동일한 놈임

  • RecyclerView의 Adapter만들때 내부적으로 ViewHolder를 만들어주었는데 이 FragmentStateAdapter역시 내부적으로 FragmentViewHolder를 지정하게됨

  • 즉, FragmentStateAdapter는 RecyclerView에서 사용되는 Adapter와 비슷한 놈으로 보면 됨
    https://developer.android.com/reference/androidx/viewpager2/adapter/FragmentStateAdapter#public-constructors_1

  • RecyclerView는 Adapter에 ViewHolder를 지정하여 구현되고, ViewPager2도 FragmentStateAdapter에 FragmentViewHolder가 지정되어 구현된다는 것
    따라서, RecyclerView와 ViewPager2는 같은 원리로 작동.

  • ViewPager2의 Adapter를 만들때 FragmentStateAdapter를 구현한다고 했는데, 이때 FragmentStateAdapter가 가진 public method 중 getItemCount()와 createFragment()는 반드시 구현해야함

    • getItemCount() : FragmentStateAdapter의 public method는 아니다. FragmentStateAdapter가 상속하는 Recyclerview.Adapter 클래스의 public method이다. 해당 Adapter가 가지고 있는 data set 안에서의 전체 아이템 수를 리턴하는 메소드이다.

    • createFragment() : FragmentStateAdapter의 public method이다. 특정 포지션에 연결된 새로운 Fragment를 제공하는 기능을 가지고 있는 메소드이다.

5. Adapter와 ViewPager2 연결하기

추가) back 버튼 클릭시 화면 슬라이드 과거로 이동시키기


✅ViewPager2와 Tab연결시키기

종속성 추가

  • Tab은 머티리얼 디자인에 속해있기 때문에 프로젝트에 머티리얼 디자인 종속성을 추가해야
  • App단위에
    implementation 'com.google.android.material:material:1.2.1'

TabLayout 만들기

  • xml에 TabLayout추가

TabLayout과 ViewPager2연결

  • Tab은 ViewPager와 연결되어 사용되는 경우가 많기 때문에 ViewPager2와 TabLayout을 연결해 볼것
  • xml파일에 TabLayout밑에 ViewPager2 추가(위 사진처럼)
  • ViewPager와 Tab을 연결하기 위해서는 TabLayoutMediator 라는 클래스를 사용해야 함. 이 클래스가 Tab과 ViewPager를 하나처럼 연결시켜줌
  • 탭의 개수를 늘리고 싶으면 Adapter안에 메소드인 getItemCount 의 리턴수 탭 수에 맞게 조절,createFragment에서 탭 수에 맞게 Fragment추가,TabLayoutMediator에서 추가된 탭 이름 추가,Adapter객체 생성 시 생성자에 주는 개수 증가하면 됨
package My_Library

import android.os.Bundle
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.viewpager2.adapter.FragmentStateAdapter
import com.example.kotlin_study.R
import com.google.android.material.tabs.TabLayout
import com.google.android.material.tabs.TabLayoutMediator
import kotlinx.android.synthetic.main.activity_view_pager2.*

class ViewPager2 : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_view_pager2)

        //ViewPager2와 Adapter연결
        val adapter = ViewPager2_Adapter(this, 3)
        viewPager2.adapter = adapter

        //각 탭들이 눌렸을때 작업할 수 있는 기반 코드
       //(없어도 무관하긴함) ViewPager2_tab_layout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
            override fun onTabReselected(tab: TabLayout.Tab?) {
                // handle tab reselect
            }

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

            override fun onTabSelected(tab: TabLayout.Tab?) {
                // handle tab select
                Toast.makeText(applicationContext, "탭 눌림", Toast.LENGTH_SHORT).show()
            }
        })

        //ViewPager와 Tab을 연결
        TabLayoutMediator(ViewPager2_tab_layout, viewPager2) { tab, position ->
            when (position) {
                0 -> tab.text = "탭1"  //탭의 이름이 됨
                1 -> tab.text = "탭2"
                2 -> tab.text = "탭3"
            }
        }.attach()

    }

    // 추가 기능 ) back 버튼 클릭시 화면 슬라이드 과거로 이동시키기
    override fun onBackPressed() {
        if (viewPager2.currentItem == 0) {
            super.onBackPressed()
        } else {
            viewPager2.currentItem = viewPager2.currentItem - 1
        }
    }

    //ViewPager2의 Adapter
    class ViewPager2_Adapter(
        fragmentActivity: FragmentActivity,
        val count: Int
    ) : FragmentStateAdapter(fragmentActivity) {
        override fun getItemCount(): Int {
            return 3
        }

        override fun createFragment(position: Int): Fragment {
            if (position == 0) {
                return ViewPager2_Fragment1()
            } else if (position == 1) {
                return ViewPager2_Fragment2()
            } else {
                return ViewPager2_Fragment3()
            }
        }
    }
}

좋은 웹페이지 즐겨찾기