TabLayout과 ViewPager2를 연결하고 각 탭의 레이아웃과 디자인을 임의로 바꾸는 샘플이다.
결과이미지
탭에 사용된 이미지
각 탭별로 선택되었을 때와 선택되지 않았을 때의 이미지를 사용하였고
각 탭별로 이미지 selector와 text컬러를 위한 selector를 구성하였다.
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
res / drawable / selector_tab0_icon.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true" android:drawable="@drawable/home"/>
<item android:drawable="@drawable/home_gray"/>
</selector>
res / color / selector_tab_text.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@color/black" android:state_selected="true"/>
<item android:color="@color/gray"/>
</selector>
Fragment 생성
상속으로 Fragment를 보다 쉽게 생성하기 위해 FragmentBase를 만들고
FragmentA, FragmentB, FragmentC는 상속을 받아 생성하였다.
FragmentBase.kt
open class FragmentBase(val _strName:String) : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_base, container, false)
}
}
FragmentA.kt 나머지 동일하고 레이아웃에서 배경색상만 바꿔줬다.
class FragmentA(_strName:String) : FragmentBase(_strName) {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_a, container, false)
}
}
AdapterTab
ViewPager2에 설정되는 Fragment리스트를 가지는 아답터이다.
class AdapterTab(val fragmentList:List<FragmentBase>, fragmentActivity: FragmentActivity)
: FragmentStateAdapter(fragmentActivity)
{
override fun getItemCount() = fragmentList.size
override fun createFragment(position: Int) = fragmentList.get(position)
}
ActivityMain의 레이아웃 구성
ViewPager2와 TabLayout 만으로 구성하였으며
탭의 선택된 바의 표시가 상단에 보이도록
tabIndicatorGravity="top"으로 설정하였으며
tabMode는 동일한 사이즈로 화면에 배치되기 위해 fixed로 설정하였다.
<?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:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context=".ActivityMain">
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewPager"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="@+id/tabLayout"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabLayout"
android:layout_width="0dp"
android:layout_height="100dp"
app:tabBackground="@color/white"
app:tabMode="fixed"
app:tabGravity="fill"
app:tabIndicatorGravity="top"
app:tabIndicatorHeight="10dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
</com.google.android.material.tabs.TabLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
탭의 레이아웃
res / layout / tab_custom.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="100dp"
android:id="@+id/cl_base">
<ImageView
android:id="@+id/iv_tab"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_marginTop="5dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<TextView
android:id="@+id/tv_tab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="TextView"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="@+id/iv_tab"
app:layout_constraintStart_toStartOf="@+id/iv_tab"
app:layout_constraintTop_toBottomOf="@+id/iv_tab" />
</androidx.constraintlayout.widget.ConstraintLayout>
ActivityMain
1. Fragment 리스트를 생성
2. 아답터를 생성
3. 아답터와 뷰페이저를 연결
4. 뷰페이저의 수만큼 탭 추가
5. 탭레이아웃과 뷰페이저 연결
위 순서대로 처리하고 처음 실행했을 때 설정탭이 선택되도록 하였다.
class ActivityMain : AppCompatActivity() {
val _binding by lazy { ActivityMainBinding.inflate(layoutInflater) }
lateinit var _listFragments:List<FragmentBase>
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContentView(_binding.root)
//.// 1. 페이지 데이터를 로드
_listFragments = listOf(FragmentA("홈"), FragmentB("프로필"), FragmentC("설정") )
//.// 2. 아답터 생성
val pagerAdapter = AdapterTab(_listFragments, this)
//.// 3. 아답터와 뷰페이저 연결
_binding.viewPager.adapter = pagerAdapter
//.// 4. 뷰페이저의 수만큼 탭 추가
for (i in _listFragments.indices) { _binding.tabLayout.addTab(_binding.tabLayout.newTab()) }
//.// 5. 탭레이아웃과 뷰페이저 연결
TabLayoutMediator(_binding.tabLayout, _binding.viewPager, true){ tab: TabLayout.Tab, i: Int ->
val customView = LayoutInflater.from(this).inflate(R.layout.tab_custom, null)
val tabText = customView.findViewById<TextView>(R.id.tv_tab)
val tabIcon = customView.findViewById<ImageView>(R.id.iv_tab)
tabText.text = _listFragments[i]._strName
tabText.setTextColor(resources.getColorStateList(R.color.selector_tab_text))
when(i){
0 -> tabIcon.setImageResource(R.drawable.selector_tab0_icon)
1 -> tabIcon.setImageResource(R.drawable.selector_tab1_icon)
2 -> tabIcon.setImageResource(R.drawable.selector_tab2_icon)
}
tab.setCustomView(customView)
customView.setTag(i)
}.attach()
_binding.tabLayout.addOnTabSelectedListener(object:OnTabSelectedListener{
//.// 탭선택시 이벤트 처리
override fun onTabSelected(tab: TabLayout.Tab?) {
tab?.customView?.let {
val nIndexFragment = it.getTag() as Int
//Toast.makeText(this@ActivityMain, _listFragments[nIndexFragment]._strName, Toast.LENGTH_SHORT).show()
}
}
override fun onTabUnselected(tab: TabLayout.Tab?) {}
override fun onTabReselected(tab: TabLayout.Tab?) {}
})
_binding.tabLayout.getTabAt(2)?.select()
}
}
<< 이것이 안드로이드다 with 코틀린 >> 참고하여 작성
'공부 > 안드로이드' 카테고리의 다른 글
Cutom TabLayout - ToggleButton (0) | 2025.09.27 |
---|---|
Custom TabLayout - Background, Indicator (0) | 2025.09.26 |
Custom View (0) | 2025.09.21 |
Fragment 전환 및 초기 데이타 전달 (0) | 2025.09.19 |
Fragment 간 데이타 전달 (0) | 2025.09.18 |