Tabs in Jetpack Compose using Official API

Saqib
Jetpack Composers
3 min readMar 21, 2023

--

This story will show how to create Tab layout in Jetpack Compose using Official Compose Foundation Dependency.

Photo by Hal Gatewood on Unsplash

I have written another story about ViewPager in Jetpack Compose using Official API. You can read it there.

Tabs are a very common design to organize information in different sections. We already are familiar about how to implement in view based design layouts But in this article we will implement it using Jetpack Compose.

Lets get started! 🚀

Dependency

Tabs API was initially part of accompanist But from Compose 1.4.0+ its part of official API. you need to add Compose Foundation dependency inside the project. You can see latest version here

implementation 'androidx.compose.foundation:foundation:1.4.0-rc01'

Your project might give errors because you might still be on an older version of Compose Compiler. You need to upgrade your Compose Compiler version to at least 1.4.0 and to achieve that you might also need to update your Kotlin version. You can see Kotlin version to Compose Compiler version mapping here.

You should update Compose Compiler version in gradle files as below

composeOptions {
kotlinCompilerExtensionVersion '1.4.3'
}

Preparation

Before implementation we need to prepare Tabs. To hold tab data we need to create a TabItem data class.

TabItem takes title and icon representing a tab. It also takes a composable screen which will be shown when the user taps on that particular tab UI.

Lets create generic composable function representing a Tab screen.

To keep it simple for this example we are just passing a text to TabScreen.

Below creating list of Tabs we want to show

Implementation

lets implement Tab Layout screen.

val pagerState = rememberPagerState()
val coroutineScope = rememberCoroutineScope()

rememberPagerState is required to manage pager state

rememberCoroutineScope is required to perform scroll animation on pagerState whenever user taps on any tab. Its used to launch coroutine outside composable function.

rememberCoroutineScope is a composable which is called to get a coroutine scope. Its tied to the composable function from where its called and gets canceled when that composable does not exist. i.e you can launch coroutines using this scope without worrying about lifecycle of coroutines.

Below creating TabRow

TabRow is a container for all tabs.

We are iterating tabs using forEachIndexed , these tabs data we already created in preparation above. We are populating each tab here inside TabRow using Tab composable.

Tab composable is representation of single tab with following properties

selected = index == pagerState.currentPage handles selection state of a Tab. if index of tab is same as pager current page then tab is in selected state.

text and icon for tab, these are optional

onClick listens for tap events on tab and calls pagerState.animateScrollToPage(index). It moves pager to the selected tab calling suspend function which is launched within a coroutine scope.

Now Lets see complete code with HorizontalPager

HorizontalPager taking total page counts and pagerState. Its same pagerState used in TabRow and Tab composables and it automatically links them together.

Thats it! hope you liked it.

Further Points

  • ScrollableTabRow composable is also available, which you can use if you have more tabs and needs a scroller to show them all. It depends upon need
  • Before this api was officially introduced in Compose Foundation dependency, it was available in accompanist dependency. If you have already used from accompanist and you want to move to official dependency then there is migration guide available here

Sources

GitHub Project

Link is below

👉 Follow for more stories on Android Development and 👏 if you liked it.

— — — — — — — — — — — — — —

GitHub | LinkedIn | Twitter

--

--

Saqib
Jetpack Composers

Senior Mobile Engineer (Android & iOS) , Berlin | Sharing my development experience