- 지난 포스팅에서 뷰페이저2를 RecyclerViewAdapter로 구현해보았다.
- RecyclerView에서는 하나의 item_list.xml을 가지고 재사용을 해서, 동일한 형태의 화면을 보여주는 것이었다면. 프래그먼트를 사용할 때는 보여줄 화면을 각각 프래그먼트로 만든다.
- 탭레이아웃을 함께 활용해보겠다
구현
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"
tools:context=".MainActivity">
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<com.google.android.material.tabs.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Monday" />
<com.google.android.material.tabs.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Tuesday" />
<com.google.android.material.tabs.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Wednesday" />
<com.google.android.material.tabs.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Wednesday" />
</com.google.android.material.tabs.TabLayout>
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewPager_idol"
android:layout_width="0dp"
android:layout_height="680dp"
app:layout_constraintTop_toBottomOf="@id/tabLayout"
app:layout_constraintStart_toStartOf="parent"
android:orientation="horizontal"/>
</androidx.constraintlayout.widget.ConstraintLayout>
FragmentA.xml ~ FragmentD.xml
- 프래그먼트 4개를 만들 것이다. 안드로이드스튜디오에서 프래그먼트로 생성하면 클래스명과 매칭되는 xml 레이아웃 파일이 자동생성된다.
- 각 프래그먼트에는 이미지뷰로 명수옹 사진을 넣어보았다.
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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"
tools:context=".FragmentA">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@string/hello_blank_fragment1" />
<ImageView
android:id="@+id/imageView1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/idol1"
android:visibility="visible"/>
</FrameLayout>
FragmentStateAdapter.kt
- RecyclerView에서의 어답터와 다르게 인자로 프래그먼트를 넘겨줘야한다.
class FragmentAdapter(fragmentList: FragmentActivity) :
FragmentStateAdapter(fragmentList)
{
var fragments = listOf<Fragment>()
override fun getItemCount(): Int {
return fragments.size
}
override fun createFragment(position: Int): Fragment {
return fragments[position]
}
}
MainActivity.kt
- 프래그먼트 어답터에 프래그먼트들을 붙이고,
- 만들어진 프래그먼트 어답터를 뷰페이저 뷰에 적용한다.
val fragmentList = listOf(FragmentA(),FragmentB(),FragmentC(),FragmentD())
val fragmentAdapter = FragmentAdapter(this)
fragmentAdapter.fragments = fragmentList
viewPargerFragment = findViewById<ViewPager2>(R.id.viewPager_idol)
viewPargerFragment.adapter = fragmentAdapter
- 그리고 탭레이아웃에 각 프래그먼트를 적용한다.
val tabLayout = findViewById<TabLayout>(R.id.tabLayout)
val tabTitles = listOf("Profile","Search","MyPage","ETC")
val iconList = ArrayList<Drawable?>()
iconList.add(ContextCompat.getDrawable(this, R.drawable.image1))
iconList.add(ContextCompat.getDrawable(this, R.drawable.image2))
iconList.add(ContextCompat.getDrawable(this, R.drawable.image3))
iconList.add(ContextCompat.getDrawable(this, R.drawable.image4))
TabLayoutMediator(tabLayout, viewPargerFragment) {tab, position ->
tab.text = tabTitles[position]
tab.icon = iconList[position]
}.attach()
TabLayout
- 여러개의 버튼이 있고, 각 버튼마다 activity나 fragment를 보여준다.
- 원래는 각 탭 버튼을 클릭했을 때 onClickListner로 행동을 지정한다. 본 글에서는 뷰페이저와 함께 사용했으므로 뷰페이저의 슬라이딩이 적용되어 페이지를 넘겨도 탭이 넘어가고, 탭을 클릭해도 슬라이딩으로 페이지가 넘어간다.
(addOnTabSelectedListener)
- 탭 선택 시 프래그먼트 이동으로 처리하는 법
tabLayout.addOnTabSelectedListener(object: TabLayout.OnTabSelectedListener {
override fun onTabSelected(tab: TabLayout.Tab?) {
val transaction = supportFragmentManager.beginTransaction()
when(tab?.text) {
"tab1" -> transaction.replace(R.id.tabContent, OneFragment() )
"tab2" -> transaction.replace(R.id.tabContent, TwoFragment() )
"tab3" -> transaction.replace(R.id.tabContent, ThreeFragment() )
}
transaction.commit()
}
override fun onTabUnselected(tab: TabLayout.Tab?) {
TODO("Not yet implemented")
}
override fun onTabReselected(tab: TabLayout.Tab?) {
TODO("Not yet implemented")
}
})
}
TabLayoutMeditator
- TabLayout과 ViewPager2를 연결해주는 객체이다.
- 탭이 선택될 때 ViewPager2의 위치를 선택한 탭과 동기화하고, 스와이프를 할 때 TabLayout의 위치를 스와이프된 위치와 동기화한다.
TabLayoutMediator(tabLayout, viewPargerFragment) {tab, position ->
tab.text = tabTitles[position]
tab.icon = iconList[position]
}.attach()
결과
- 탭을 위에 두고 아이콘과 메뉴명을 지정했다. 아이콘은 큰 이미지라 그런지 안나온다 쩝..
- 탭을 넘기거나 이미지를 슬라이딩할 때마다 각 프래그먼트가 보인다.
![업로드중..]()