이전 글에서 RecyclerView.Adapter을 이용하여 ViewPager2를 만드는 방법에 대해 알아봤다.
이번에는 FragmentStateAdapter를 이용하여 ViewPager2를 만들고 TabLayout을 붙여보려고 한다.
ViewPager에서 봤듯 FragmentStatePagerAdapter는 deprecated 되었으며
FragmentStateAdapter 로 대체되었다.
FragmentStatePagerAdapter -> FragmentStateAdapter
PagerAdapter -> RecyclerView.Adapter
addPageChangeListener -> registerOnPageChangeCallback
때문에 FragmentStatePagerAdapter와 비슷하게 작동한다.
그리고 Docs에서 FragmentStateAdapter를 찾아보면
FragmentStateAdapter의 부모 클래스가 RecyclerView.Adapter라고 나와있다.
RecyclerView의 Paging 버전 같은 느낌이다.
1. FragmentStateAdapter
FragmentStateAdapter는 RecyclerView.Adapter로 구현할 때와 다르게 인자 값으로 Fragment를 넘겨줘야 한다.
때문에 Fragment를 하나의 View로써 사용하는 RecyclerView와 같은 느낌을 받았다.
Adapter 내부에 Fragment를 담을 ArrayList<Fragment> 변수를 만들고 이를 통해 Fragment들을 핸들링한다.
FragmentStateAdapter의 부모 클래스가 RecyclerView.Adapter이기 때문에
fragments에 대해 add 또는 remove 할 때 적절한 notifyItem 메소드를 호출해준다.
PagerFragmentStateAdapter.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
class PagerFragmentStateAdapter(fragmentActivity: FragmentActivity): FragmentStateAdapter(fragmentActivity) {
var fragments : ArrayList<Fragment> = ArrayList()
override fun getItemCount(): Int {
return fragments.size
}
override fun createFragment(position: Int): Fragment {
return fragments[position]
}
fun addFragment(fragment: Fragment) {
fragments.add(fragment)
notifyItemInserted(fragments.size-1)
}
fun removeFragment() {
fragments.removeLast()
notifyItemRemoved(fragments.size)
}
}
|
cs |
2. ViewPagerFragment
ViewPagerFragment에 ViewPager2를 꽉 차게 두고 아래 3개의 Fragment를 띄우려고 한다.
fragment_view_pager.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
tools:context=".ViewPagerFragment">
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
|
cs |
pagerAdapter 변수를 PagerFragmentStateAdapter() 로 생성하여
3개의 Fragment에 addFragment() 한 후 viewPager.adapter에 지정한다.
ViewPagerFragment.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
class ViewPagerFragment : Fragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_view_pager, container, false)
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
val pagerAdapter = PagerFragmentStateAdapter(requireActivity())
// 3개의 Fragment Add
pagerAdapter.addFragment(FirstFragment())
pagerAdapter.addFragment(SecondFragment())
pagerAdapter.addFragment(ThirdFragment())
// Adapter
viewPager.adapter = pagerAdapter
viewPager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
override fun onPageSelected(position: Int) {
super.onPageSelected(position)
Log.e("ViewPagerFragment", "Page ${position+1}")
}
})
}
}
|
cs |
참고로 ViewPager2를 Right-to-Left로 설정하고 싶을 경우
xml에서 ViewPager2의 layoutDirection값을 rtl로 지정하면 된다.
3. TabLayout
TabLayout은 HorizontalScrollView를 확장하여 만들어졌으며
때문에 기본적으로 Horizontal로 Scroll할 수 있다.
화면에 TabLayout을 추가하여 ViewPager2와 연동해보자.
xml에 TabLayout을 추가한다.
fragment_view_pager.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
tools:context=".ViewPagerFragment">
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="40dp"/>
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
|
cs |
기존의 ViewPager에서는 내부에 childView로 TabLayout을 넣고 gravity를 지정하여 연동할 수 있었는데
ViewPager2에서는 그렇게 할 경우 ViewPager2 does not support direct child views 에러가 뜨면서 앱이 죽는다.
추가한 TabLayout에 대해 구현하고 attach()한다.
ViewPagerFragment.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
class ViewPagerFragment : Fragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_view_pager, container, false)
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
val pagerAdapter = PagerFragmentStateAdapter(requireActivity())
// 3개의 Fragment Add
pagerAdapter.addFragment(FirstFragment())
pagerAdapter.addFragment(SecondFragment())
pagerAdapter.addFragment(ThirdFragment())
// Adapter
viewPager.adapter = pagerAdapter
viewPager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
override fun onPageSelected(position: Int) {
super.onPageSelected(position)
Log.e("ViewPagerFragment", "Page ${position+1}")
}
})
// TabLayout attach
TabLayoutMediator(tabLayout, viewPager) { tab, position ->
tab.text = "Tab ${position+1}"
}.attach()
}
}
|
cs |
TabLayout에 이미지를 입혀 응용하면
좀 더 그럴싸한 ViewPager2+TabLayout을 만들 수 있을 것 같다.
끝.
'이상 > Andrioid' 카테고리의 다른 글
[Android/Kotlin] 커스텀 달력 만들기 (11) | 2021.01.10 |
---|---|
[Android/Kotlin] ViewPager2 - Infinite Loop (10) | 2021.01.09 |
[Android/Kotlin] ViewPager2 - RecyclerView.Adapter 사용하기 (0) | 2020.12.01 |
[Android/Kotlin] ViewPager 사용하기 (0) | 2020.11.25 |
[Android/Kotlin] Fragment에 대하여 (2) | 2020.11.24 |