Tabs with View Pager in Kotlin
This document describes step-by-step procedure to create a Tab layout with ViewPager in Kotlin.
Screen Shots:
Step 1: Create a Layout with Tablayout and ViewPager Widgets as below:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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=".Kotlin_tabs.TabActivity"
android:orientation="vertical">
<android.support.design.widget.TabLayout
android:id="@+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabMode="fixed"
android:background="?attr/colorPrimary"
android:minHeight="?attr/actionBarSize"
app:tabGravity="fill"
app:tabTextColor="#FFF"
app:tabSelectedTextColor="@color/colorAccent"
/>
<android.support.v4.view.ViewPager
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
Step 2: Create an Activity that attaches required Fragments to ViewPager and Viewpager to TabLaout as below:
package com.mvvm.kot.Kotlin_tabs
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.support.design.widget.TabLayout
import android.support.v4.app.Fragment
import android.support.v4.app.FragmentManager
import android.support.v4.app.FragmentStatePagerAdapter
import android.support.v4.view.ViewPager
import android.widget.TableLayout
import com.mvvm.kot.Kotlin_tabs.containerViews.RootTab1Fragment
import com.mvvm.kot.Kotlin_tabs.containerViews.RootTab2Fragment
import com.mvvm.kot.Kotlin_tabs.containerViews.RootTab3Fragment
import com.mvvm.kot.Kotlin_tabs.views.RegistrationFragment
import com.mvvm.kot.Kotlin_tabs.views.RetrofitRoomKotlinFragment
import com.mvvm.kot.Kotlin_tabs.views.Retrofit_list
import com.mvvm.kot.Kotlin_tabs.views.SimpleListFragment
import com.mvvm.kot.R
class TabActivity : AppCompatActivity() {
lateinit var viewPager:ViewPager
lateinit var tabLayout:TabLayout
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_tab)
initViews()
setStatePageAdapter()
tabLayout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
override fun onTabSelected(tab: TabLayout.Tab) {
viewPager.currentItem = tab.position
val fm = supportFragmentManager
val ft = fm.beginTransaction()
val count = fm.backStackEntryCount
if (count >= 1) {
supportFragmentManager.popBackStack()
}
ft.commit()
}
override fun onTabUnselected(tab: TabLayout.Tab) {
// setAdapter();
}
override fun onTabReselected(tab: TabLayout.Tab) {
// viewPager.notifyAll();
}
})
}
private fun initViews(){
viewPager = findViewById<ViewPager>(R.id.pager)
tabLayout = findViewById<TabLayout>(R.id.tabs)
}
private fun setStatePageAdapter(){
val myViewPageStateAdapter:MyViewPageStateAdapter = MyViewPageStateAdapter(supportFragmentManager)
myViewPageStateAdapter.addFragment(RootTab1Fragment(),"Registration")
myViewPageStateAdapter.addFragment(RootTab2Fragment(),"MVVMRetroList")
myViewPageStateAdapter.addFragment(RootTab3Fragment(),"MVVMList")
viewPager.adapter=myViewPageStateAdapter
tabLayout.setupWithViewPager(viewPager,true)
}
class MyViewPageStateAdapter(fm:FragmentManager):FragmentStatePagerAdapter(fm){
val fragmentList:MutableList<Fragment> = ArrayList<Fragment>()
val fragmentTitleList:MutableList<String> = ArrayList<String>()
override fun getItem(position: Int): Fragment {
return fragmentList.get(position)
}
override fun getCount(): Int {
return fragmentList.size
}
override fun getPageTitle(position: Int): CharSequence? {
return fragmentTitleList.get(position)
}
fun addFragment(fragment:Fragment,title:String){
fragmentList.add(fragment)
fragmentTitleList.add(title)
}
}
}
Step 3: Create 3 container layouts to hold fragments for each Tab since we display 3 tabs in the programme
fragment_root_tab1.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"
android:id="@+id/root_container1"
tools:context=".Kotlin_tabs.containerViews.RootTab1Fragment">
</FrameLayout>
fragment_root_tab2.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"
android:id="@+id/root_container2"
tools:context=".Kotlin_tabs.containerViews.RootTab1Fragment">
</FrameLayout>
fragment_root_tab3.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"
android:id="@+id/root_container3"
tools:context=".Kotlin_tabs.containerViews.RootTab3Fragment">
</FrameLayout>
Step 3 : Create 3 container Fragments as below where we replace frame layouts with actual Fragments.
Check for onCreateView() where we replace with actual Fragment.
RootTab1Fragment:
package com.mvvm.kot.Kotlin_tabs.containerViews
import android.os.Bundle
import android.support.v4.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.mvvm.kot.Kotlin_tabs.views.RegistrationFragment
import com.mvvm.kot.Kotlin_tabs.views.RetroFitListChildFragment
import com.mvvm.kot.R
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private const val ARG_PARAM1 = "param1"
private const val ARG_PARAM2 = "param2"
/**
* A simple [Fragment] subclass.
* Use the [RootTab1Fragment.newInstance] factory method to
* create an instance of this fragment.
*
*/
class RootTab1Fragment : Fragment() {
// TODO: Rename and change types of parameters
private var param1: String? = null
private var param2: String? = null
private var root1View: View? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.let {
param1 = it.getString(ARG_PARAM1)
param2 = it.getString(ARG_PARAM2)
}
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
// Inflate the layout for this fragment
root1View = inflater.inflate(R.layout.fragment_root_tab1, container, false)
activity!!.supportFragmentManager.beginTransaction().replace(R.id.root_container1, RegistrationFragment()).commit()
return root1View
}
companion object {
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* @param param1 Parameter 1.
* @param param2 Parameter 2.
* @return A new instance of fragment RootTab1Fragment.
*/
// TODO: Rename and change types and number of parameters
@JvmStatic
fun newInstance(param1: String, param2: String) =
RootTab1Fragment().apply {
arguments = Bundle().apply {
putString(ARG_PARAM1, param1)
putString(ARG_PARAM2, param2)
}
}
}
}
RootTab2Fragment:
package com.mvvm.kot.Kotlin_tabs.containerViews
import android.os.Bundle
import android.support.v4.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.mvvm.kot.Kotlin_tabs.views.RegistrationFragment
import com.mvvm.kot.Kotlin_tabs.views.RetrofitRoomKotlinFragment
import com.mvvm.kot.R
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private const val ARG_PARAM1 = "param1"
private const val ARG_PARAM2 = "param2"
/**
* A simple [Fragment] subclass.
* Use the [RootTab1Fragment.newInstance] factory method to
* create an instance of this fragment.
*
*/
class RootTab2Fragment : Fragment() {
// TODO: Rename and change types of parameters
private var param1: String? = null
private var param2: String? = null
private var root2View: View? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.let {
param1 = it.getString(ARG_PARAM1)
param2 = it.getString(ARG_PARAM2)
}
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
// Inflate the layout for this fragment
root2View = inflater.inflate(R.layout.fragment_root_tab2, container, false)
activity!!.supportFragmentManager.beginTransaction().replace(R.id.root_container2, RetrofitRoomKotlinFragment()).commit()
return root2View;
}
companion object {
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* @param param1 Parameter 1.
* @param param2 Parameter 2.
* @return A new instance of fragment RootTab1Fragment.
*/
// TODO: Rename and change types and number of parameters
@JvmStatic
fun newInstance(param1: String, param2: String) =
RootTab2Fragment().apply {
arguments = Bundle().apply {
putString(ARG_PARAM1, param1)
putString(ARG_PARAM2, param2)
}
}
}
}
RootTab3Fragment:
package com.mvvm.kot.Kotlin_tabs.containerViews
import android.os.Bundle
import android.support.v4.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.mvvm.kot.Kotlin_tabs.views.RetrofitRoomKotlinFragment
import com.mvvm.kot.Kotlin_tabs.views.SimpleListFragment
import com.mvvm.kot.R
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private const val ARG_PARAM1 = "param1"
private const val ARG_PARAM2 = "param2"
/**
* A simple [Fragment] subclass.
* Use the [RootTab3Fragment.newInstance] factory method to
* create an instance of this fragment.
*
*/
class RootTab3Fragment : Fragment() {
// TODO: Rename and change types of parameters
private var param1: String? = null
private var param2: String? = null
private var root3View: View? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.let {
param1 = it.getString(ARG_PARAM1)
param2 = it.getString(ARG_PARAM2)
}
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
// Inflate the layout for this fragment
root3View = inflater.inflate(R.layout.fragment_root_tab3, container, false)
activity!!.supportFragmentManager.beginTransaction().replace(R.id.root_container3, SimpleListFragment()).commit()
return root3View
}
companion object {
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* @param param1 Parameter 1.
* @param param2 Parameter 2.
* @return A new instance of fragment RootTab3Fragment.
*/
// TODO: Rename and change types and number of parameters
@JvmStatic
fun newInstance(param1: String, param2: String) =
RootTab3Fragment().apply {
arguments = Bundle().apply {
putString(ARG_PARAM1, param1)
putString(ARG_PARAM2, param2)
}
}
}
}
Step 4:
Similar create the corresponding Fragments to be replaced in each RootFragment.
Source code uploaded at