Overview
Tab Layout
This blog is about implementing tab layout in Android using Kotlin.
Tab Layout with view pager
Including tab layout & view pager in xml
<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:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="com.MainActivity"> <android.support.v7.widget.Toolbar android:id="@+id/toolBar" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/colorPrimary" /> <android.support.design.widget.TabLayout android:id="@+id/tabLayout" android:layout_width="match_parent" android:layout_height="wrap_content" app:tabMode="fixed" /> <android.support.v4.view.ViewPager android:id="@+id/viewPager" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout>
Create the fragments that you want to display inside the view pager when tab is selected
Here, we will display different colored background for each fragment in view pager.
I’ll show one fragment here, for instance.
XML file:-
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/colorAccent" android:orientation="vertical"> <FrameLayout android:id="@+id/frag1_frame" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout>
Kotlin file:-
class Frag1 : android.support.v4.app.Fragment() { override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? { val view = inflater!!.inflate(R.layout.frag1_layout, container, false) return view } }
Implementing FragmentStatePager Adapter
class ViewPagerAdapter(fm: FragmentManager) : FragmentPagerAdapter(fm) { private val fragments = ArrayList<Fragment>() private val tabNames = ArrayList<String>() fun addFragmentTabName(fragment: Fragment, tabName: String) { fragments.add(fragment) tabNames.add(tabName) } override fun getItem(position: Int): Fragment { return fragments[position] } override fun getCount(): Int { return fragments.size } override fun getPageTitle(position: Int): CharSequence { return tabNames[position] } }
Here, I have used 2 arrayLists; one for storing fragments and 1 for storing names of tabs.
To display names of tabs on tab selection, getPageTitle( ) method is overridden in adapter and it returns name of the tab at selected position.
To display fragment on tab selection, getItem( ) method is overridden in adapter which returns the fragment at selected position.
Code in MainActivity.kt
class MainActivity : AppCompatActivity() { private var viewPagerAdapter: ViewPagerAdapter? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) init() viewPager!!.offscreenPageLimit = 3 //upto 3 off screen pages will not get destroyed. default is 1 setSupportActionBar(toolBar) passFragmentsIntoAdapter() setAdapter() setIconsInTabLayout() } internal fun init() { viewPagerAdapter = ViewPagerAdapter(supportFragmentManager) } internal fun passFragmentsIntoAdapter() { viewPagerAdapter!!.addFragmentTabName(Frag1(), "Frag1") viewPagerAdapter!!.addFragmentTabName(Frag2(), "Frag2") viewPagerAdapter!!.addFragmentTabName(Frag3(), "Frag3") } internal fun setAdapter() { viewPager!!.adapter = viewPagerAdapter tabLayout!!.setupWithViewPager(viewPager) } internal fun setIconsInTabLayout() { //should be called after setting adapter and tab layout //tab titles can also be set here using setText tabLayout!!.getTabAt(0)!!.setIcon(R.mipmap.ic_launcher) tabLayout!!.getTabAt(1)!!.setIcon(R.mipmap.ic_launcher) tabLayout!!.getTabAt(2)!!.setIcon(R.mipmap.ic_launcher) } }
Tab Layout without view pager
Including tab layout & a frame layout in xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="com.MainActivity"> <android.support.design.widget.TabLayout android:id="@+id/actMain_tabLayout" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#336699" /> <FrameLayout android:id="@+id/actMain_frame" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1" /> </LinearLayout>
Create the fragments that you want to display when tab is selected
Here, we will display different colored background for each fragment.
I’ll show one fragment here, for instance.
XML file:-
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/colorAccent" android:orientation="vertical"> <FrameLayout android:id="@+id/frag1_frame" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout>
Kotlin file:-
class Frag1 : android.support.v4.app.Fragment() { override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? { val view = inflater!!.inflate(R.layout.frag1_layout, container, false) return view } }
Code in MainActivity.kt
class MainActivity : AppCompatActivity() { private var fragmentTransaction: FragmentTransaction? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) addFirstFrag() designTabLayout() actMain_tabLayout!!.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener { override fun onTabSelected(tab: TabLayout.Tab?) { setCurrentTabFragment(actMain_tabLayout!!.getSelectedTabPosition()) } override fun onTabUnselected(tab:TabLayout.Tab?){ } override fun onTabReselected(tab:TabLayout.Tab?) { } }) } internal fun addFirstFrag() { fragmentTransaction = fragmentManager!!.beginTransaction() fragmentTransaction!!.replace(R.id.actMain_frame, Frag1()) fragmentTransaction!!.addToBackStack("") fragmentTransaction!!.commit() } internal fun designTabLayout() { actMain_tabLayout!!.addTab(actMain_tabLayout!!.newTab().setIcon(R.mipmap.ic_launcher).setText("1")) actMain_tabLayout!!.addTab(actMain_tabLayout!!.newTab().setIcon(R.mipmap.ic_launcher).setText("2")) actMain_tabLayout!!.addTab(actMain_tabLayout!!.newTab().setIcon(R.mipmap.ic_launcher).setText("3")) } internal fun addFrag(fragment: Fragment) { fragmentTransaction = fragmentManager!!.beginTransaction() fragmentTransaction!!.replace(R.id.actMain_frame, fragment) fragmentTransaction!!.addToBackStack("") fragmentTransaction!!.commit() } internal fun setCurrentTabFragment(pos: Int) { when (pos) { 0 -> addFrag(Frag1()) 1 -> addFrag(Frag2()) 2 -> addFrag(Frag3()) } } }
First, we have to design the tab layout before loading fragments in frame layout i.e. setting icon and text for each tab.
Then, I have loaded 1st fragment in the frame layout.
Finally, I have used addOnTabSelectedListener( ) to detect the selected tab and then on selection of the tab, I have loaded the respective fragment in the frame.
Conclusion
Tab layouts are in fashion now-a-days. We see them in facebook, whatsapp and other such giant apps. Hence, it is a good idea to learn to code tab layouts in Kotlin because it will be a must requirement in future projects.