230913 ViewPager2, TabLayout
1. 빈 프래그먼트를 3개 만들어준다. (예: FirstFragment, SecondFragment, ThirdFragment)
ViewPagerAdapter
class ViewPagerAdapter(fragmentActivity: FragmentActivity) : FragmentStateAdapter(fragmentActivity) {
override fun createFragment(position: Int): Fragment {
return when(position){
0 -> FirstFragment()
1 -> SecondFragment()
else -> ThirdFragment()
}
}
override fun getItemCount():Int =3
}
2.
ㄱ. FragmentStateAdapter : ViewPager2에 표시될 프래그먼트를 관리하는데 ViewPager2를 사용하기위해 상속받는다.
ㄴ. override fun createFragment : FragmentStateAdapter를 상속받을때 반드시 써줘야하는 추상 메서드이고, ViewPager2에 표시될 Fragment를 생성한다.
ㄷ. position에 따라서 각각 내가 보고싶은 Fragment를 생성한다. (예를들어 첫번째 페이지는 0번째이고, 첫번째 페이지에 FirstFragment를 화면에 보이게하고싶으면 위처럼 코드를 쓰면 된다.)
ㄹ. getItemCount : 뷰페이저에서 몇개의 프래그먼트를 표시하는지 반환해준다.
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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">
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="@+id/tabLayout"
app:layout_constraintTop_toTopOf="parent" />
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent">
<com.google.android.material.tabs.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<com.google.android.material.tabs.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<com.google.android.material.tabs.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</com.google.android.material.tabs.TabLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
3. MainActivity에서 탭레이아웃과 뷰페이저를 위와 같이 표시할것이다.
MainActivity
class MainActivity : AppCompatActivity() {
private val binding by lazy { ActivityMainBinding.inflate(layoutInflater) }
private val tabList = listOf("FirstFragment", "SecondFragment", "ThirdFragment")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
binding.viewPager.adapter = ViewPagerAdapter(this)
TabLayoutMediator(binding.tabLayout, binding.viewPager) { tab, position ->
tab.text = tabList[position]
}.attach()
}
}
4.
ㄱ. binding : 3에서 작성한 xml을 사용할것이기 때문에 해당 xml을 binding해준다.
ㄴ. tabList : TabLayout에 해당 탭이 뭔지 표시해줄 이름표
ㄷ. xml에있는 뷰페이저 id : viewPager를 바인딩해주고 그 adapter를 처음에 만든 ViewPagerAdapter와 연동해준다.
ㄹ. TabLayoutMediator : TabLayout과 ViewPager2를 연동시키고 xml의 tabLayout의 id와 viewPager의 id를 파라미터로 받아온다.
ㅁ. tab 은 현재 탭, position은 현재 탭의 위치를 나타낸다.
ㅂ. tab.text (각텝의 이름표에 들어갈 text) 는 tabList의 position번째 있는 데이터를 넣어준다.
ㅅ. attach() : TabLayoutMediator와 ViewPager2와 연동하고 적용하기위해 해당 매서드를 호출한다.
여기까지 하면 기본 ViewPager2 & Tablayout 이 적용된다.(위 코드는 0 ->1, 1 ->2 페이지로만 전환이 가능하다.)
추가 (onCreate 내부)
: 0->2, 2->0 페이지전환도 가능하다.
binding.viewPager.registerOnPageChangeCallback(object: ViewPager2.OnPageChangeCallback(){
var currentState = 0
var currentPosition = 0
override fun onPageScrolled(
position: Int,
positionOffset: Float,
positionOffsetPixels: Int
) {
if(currentState == ViewPager2.SCROLL_STATE_DRAGGING&¤tPosition == position){
if (currentPosition == 0) binding.viewPager.currentItem =2
else if(currentPosition ==2) binding.viewPager.currentItem =0
}
super.onPageScrolled(position, positionOffset, positionOffsetPixels)
}
override fun onPageSelected(position: Int) {
currentPosition = position
super.onPageSelected(position)
}
override fun onPageScrollStateChanged(state: Int) {
currentState = state
super.onPageScrollStateChanged(state)
}
})
ㄱ. registerOnPagerChangeCallBack : 클릭이벤트와같이 ViewPager2의 페이지전환을 감지하는 이벤트
ㄴ. currentState(현재 상태), currentPosition(현재위치) 초기값 지정
ㄷ. currentState == ViewPager2.SCROLL_STATE_DRAGGING : ViewPager의 현재 상태가 화면을 드래그해서 스와이프중인 상태일때
ㄹ. currentPosition == position : ViewPager2에서 선택된 페이지의 위치 ( 예를들어 currentPosition이 0이면 현재 선택된 페이지는 첫번째 페이지이다.)
ㅁ. if(currentPosition ==0 ) binding.viewPager.currentItem =2 : currentPosition 이 0일때 뷰페이저의 현재 아이템을 2번째 페이지로 변경한다. ( 현재 0번째 페이지에서 스와이프 중일때 2번째 페이지로 변경한다.)
ㅂ. else if(currentPosition ==2) binding.viewPager.currentItem = 0 : currentPosition 이 2일때 뷰페이저의 현재 아이템을 0번째 페이지로 변경한다. (현재 2번째 페이지에서 스와이프 중일때 0번째 페이지로 변경한다.)
ㅅ. override fun onPageSelected : 페이지 선택을 감지한다.
-currentPosition = position : 현재 선택된 페이지를 currentPosition에 넣어준다.
ㅇ. onPageScrollStateChanged : 페이지가 전환되는것을 감지한다.
- currentState = state : 위 코드에서는 state(스와이프 중인 상태)를 currentState에 저장한다.
썸네일 출처