Implement TabLayout with ViewPager in Android Jetpack Compose
By: Mr Umbrella
Tags: Tablayout, Viewpager, Transitions, Android, Animation

Implement TabLayout with ViewPager in Android Jetpack Compose

How we can use pager with tabs to slide between pages with a smooth animation and a good infinite looping effect. Mr Umbrella Follow Jul 14 · 4 min read

Introduction

Slide between pages are common with UIs like onboarding, setup wizards… I think you’ve already know how to do page slide by using ViewPager . In case you are looking for a replacement of ViewPager in Compose, I suggest you to look at this Pager library.

This library is currently experimental. All of the APIs are flagged as an @ExperimentalPagerApi , but it handles the core pager functionality very well.

In this post let’s check how we can use pager with tabs to slide between pages with a smooth animation and a good infinite looping effect.

Let’s begin! 🥰

Step1: Project Setup

First, please check the Pager website to get the latest version.

And then add the below to your app’s build.gradle :

dependencies {

implementation "com.google.accompanist:accompanist-pager:0.12.0"

}

Step2: HorizontalPager

To implement tabs we will be using two components that are HorizontalPager and PagerState .

HorizontalPager is a ViewPager in compose environment, allows user to horizontally swipe between pages. It is unnecessary to create all the pages at once because doing this would use a lot of memory and user would never swipe through all the pages. By default, HorizontalPager only creates the current page as well as the off-screen pages to the left and to the right of the current page. Pages beyond this limit will be removed.

What is the solution of this problem?

Yeah there is: PagerState

This is a state of HorizontalPager that we want to keep across compositions. Let’s have a look at the method signature of PagerState :

We can see here that there are 5 available properties that we can pass to the rememberPagerState function:

pageCount : the number of pages. This is required.

: the number of pages. This is required. initialPage : the initial page, the default value is 0.

: the initial page, the default value is 0. initialPageOffset : the initial page offset.

: the initial page offset. initialOffscreenLimit : defines the number of pages that should be retained on either side of the current page. This value requires a minimum of 1 offscreen pages. You need to KEEP A CLOSE LOOK ON THE MEMORY MANAGEMENT. In case there are many items like images and animations, if you cache all of them, this probably will result with an OutOfMemoryError.

: defines the number of pages that should be retained on either side of the current page. This value requires a minimum of 1 offscreen pages. You need to KEEP A CLOSE LOOK ON THE MEMORY MANAGEMENT. In case there are many items like images and animations, if you cache all of them, this probably will result with an OutOfMemoryError. infiniteLoop : the handy property. If true, you can swipe from first to last page with just one step.

With these properties in mind, we can create a PagerState and pass it to HorizontalPager .

Let’s have a look at the method signature of HorizontalPager:

We can see here that there are 9 available properties that we can pass to the HorizontalPager function:

state : the PagerState that we created above. This is required.

: the that we created above. This is required. modifier : the modifier to be applied to the pager.

: the modifier to be applied to the pager. reverseLayout : when true items will be composed from the end to the start.

: when true items will be composed from the end to the start. itemSpacing : horizontal spacing to add between items.

: horizontal spacing to add between items. dragEnabled : when false the user can not swipe between page.

: when false the user can not swipe between page. flingBehavior : logic describing fling behavior.

: logic describing fling behavior. verticalAlignment , horizontalAlignment : help to align the layout’s children.

, : help to align the layout’s children. content : take another Composable function to create the page.

Step3: Integration with Tabs

You can check out this link to see my article how to implement tab in jetpack compose.

Let’s create a screen with 4 tabs and a pager links to them. I’ve set the off-screen to 2, turn on infinite loop and the initial page is at the second. When the tab is clicked, there will be an animation to slide the page to that tab. Here are the codes:

I used animateScrollToPage() to jump with animation to the corresponding page depending on which tab users press. Use scrollToPage() instead to jump instantly without seeing other pages. These 2 methods are suspend functions so wrap into a coroutineScope.

If you find issues in executing the code snippets please check out the GitHub repo Tab-Compose for help.