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