설명할 미션 : 앨범 화면(AlbumFragment)에 TabLayout + Viewpager2를 구현하고 Viewpager2 에 DetailFragment, VideoFragment 연결하기
우선 어댑터 클래스를 만든다. 일단 전체 코드를 보자.
package com.example.flo.albumfrag
import android.os.Bundle
import androidx.fragment.app.Fragment
import androidx.viewpager2.adapter.FragmentStateAdapter
import com.example.flo.albumfrag.VideoFragment
import com.example.flo.dataclasses.Album
import com.example.flo.albumfrag.DetailFragment
import com.google.gson.Gson
//수록곡 전달을 위해 인자 하나 더 추가 -> 나 이거 왜써놓은거지 ㅋㅋ
class AlbumVPAdapter(fragment: Fragment, private val album: Album) : FragmentStateAdapter(fragment){
override fun getItemCount(): Int = 3
override fun createFragment(position: Int): Fragment {
return when(position) {
0 -> SongFragment().apply {
arguments = Bundle().apply {
val albumJson = Gson().toJson(album)
putString("album", albumJson)
}
}
1 -> {
DetailFragment()
}
else -> VideoFragment()
}
}
}
차근차근 분석해보자.
class AlbumVPAdapter(fragment: Fragment) : FragmentStateAdapter(fragment)
클래스를 만들고 인자로 프래그먼트를 넣는다. FragStateAdapter이라는 추상 클래스를 상속 받아 어댑터 클래스로서의 역할을 하게 만든다.
override fun getItemCount(): Int = 3
override fun createFragment(position: Int): Fragment {
return when(position) {
0 -> SongFragment().apply {
arguments = Bundle().apply {
val albumJson = Gson().toJson(album)
putString("album", albumJson)
}
}
1 -> {
DetailFragment()
}
else -> VideoFragment()
}
}
일단 저기서 데이터 전달을 다루는 부분은 무시하자. FragStateAdapter이라는 추상 클래스를 상속받았으므로 getItemCount(): Int와 createFragment(position: Int): Fragment 라는 2개의 메서드를 필수로 구현해주어야한다. 뷰페이저에 들어갈 프래그먼트가 총 3개이므로 getItemCount는 3을 반환하도록 한다. 그리고 createFragment메서드는 when문을 사용해 position값에 따라 반환할 프래그먼트 객체를 다르게 한다.
- position : 뷰페이저의 페이지 번호라고 생각하면 된다, 처음에 getItemCount를 활용해서 뷰 페이저의 페이지 수를 지정하면, 내부적으로 뷰페이저의 첫번째 페이지는 position=0, 두번째는 position=1 세번째는 position=2로 지정된다. 그리고 createFragment메서드에서 when문을 사용해 position=0인 페이지, 즉 첫번째 페이지를 보여지게 할 때 그 페이지에 SongFragment가 나오도록 하는 것이다.
각 페이지에 들어갈 프래그먼트들은 제작해 놓았다고 가정하고 이제 AlbumFragment.kt로 가보자. 여기서 다음과 같은 코드를 작성한다.
//AlbumFragment.kt
val albumAdapter = AlbumVPAdapter(this, album)
binding.albumContentVp.adapter = albumAdapter
이런 식으로 프래그먼트에 어댑터를 등록해 준다.
이제 탭 레이아웃과 뷰페이저를 연동해 보자. fragment_album.xml에 탭레이아웃을 만들어 놓았다고 가정한다.
AlbumFragment.kt에 다음과 같은 코드를 작성한다.
//AlbumFragment.kt
private val information = arrayListOf("수록곡", "상세정보", "영상")
//중략
TabLayoutMediator(binding.albumContentTb, binding.albumContentVp) { tap, position ->
tap.text = information[position]
}.attach()
- TabLayoutMediator : 탭레이아웃과 뷰페이저를 연결하는 중재자 클래스. 탭이 선택될 때 뷰페이지를 동기화하고 뷰페이지가 선택될 때 탭레이아웃을 동기화. 인자를 총 3개 받는데, 탭레이아웃 객체, 뷰페이저객체, 탭과 포지션을 어떻게 연결할지 정의하는 함수 이렇게 3개를 받는다. 3번째 인자는 람다식으로 썼다.
- 람다식 내부는 각 탭이 어떤 텍스트를 가질 지 설정하는 부분이다. position은 위에 설명한 것처럼 뷰페이저의 페이지번호이고, 탭은 해당 위치의 탭 객체이다. 위에 arraylist인 information을 생성해 놓았는데, 여기서 각 탭의 텍스트로 information[position] 값을 설정한다.
- 그 뒤 TabLayoutMediator의 attach()메서드를 호출하여 탭과 뷰페이저를 연결한다.
'안드로이드 스터디' 카테고리의 다른 글
| RecyclerView 클릭 이벤트 구현 (0) | 2025.11.02 |
|---|---|
| RecyclerView를 써 보자! (0) | 2025.11.02 |
| HomeFragment.kt 분석 (0) | 2025.11.01 |
| 메인액티비티 코드 분석 (0) | 2025.11.01 |
| 코틀린 기본 문법 정리 - 익명클래스와 익명객체 (0) | 2025.11.01 |