Search icon
Arrow left icon
All Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Newsletters
Free Learning
Arrow right icon
Modern Android 13 Development Cookbook

You're reading from  Modern Android 13 Development Cookbook

Product type Book
Published in Jul 2023
Publisher Packt
ISBN-13 9781803235578
Pages 322 pages
Edition 1st Edition
Languages
Author (1):
Madona S. Wambua Madona S. Wambua
Profile icon Madona S. Wambua

Table of Contents (15) Chapters

Preface 1. Chapter 1: Getting Started with Modern Android Development Skills 2. Chapter 2: Creating Screens Using a Declarative UI and Exploring Compose Principles 3. Chapter 3: Handling the UI State in Jetpack Compose and Using Hilt 4. Chapter 4: Navigation in Modern Android Development 5. Chapter 5: Using DataStore to Store Data and Testing 6. Chapter 6: Using the Room Database and Testing 7. Chapter 7: Getting Started with WorkManager 8. Chapter 8: Getting Started with Paging 9. Chapter 9: Building for Large Screens 10. Chapter 10: Implementing Your First Wear OS Using Jetpack Compose 11. Chapter 11: GUI Alerts – What’s New in Menus, Dialog, Toast, Snackbars, and More in Modern Android Development 12. Chapter 12: Android Studio Tips and Tricks to Help You during Development 13. Index 14. Other Books You May Enjoy

Implementing your first tab layout with a view pager using Jetpack Compose

In Android development, having a slide between pages is very common, with a significant use case being onboarding or even when you are trying to display specific data in a tabbed, carousel way. In this recipe, we will build a simple horizontal pager in Compose and see how we can utilize the new knowledge to build better and more modern Android apps.

Getting ready

In this example, we will build a horizontal pager that changes colors when selected to show the state is selected. We will look into states in Chapter 3, Handling the UI State in Jetpack Compose and Using Hilt, for better understanding. Open the Compose Basics project to get started.

How to do it…

Follow these steps to build your tab carousel:

  1. Add the following pager dependencies to build.gradle(Module:app):
    implementation "com.google.accompanist:accompanist-pager:0.x.x"
    implementation "com.google.accompanist:accompanist-pager-indicators:0.x.x"
    implementation 'androidx.Compose.material:material:1.x.x'

Jetpack Compose offers Accompanist, a group of libraries that aims to support it with commonly required features by developers – for instance, in our case, the pager.

  1. In the same project from previous recipes, let’s create a package and call it pagerexample; inside it, create a Kotlin file and call it CityTabExample; inside this file, create a composable function and call it CityTabCarousel:
    @Composable
    fun CityTabCarousel(){}
  2. Now, let us go ahead and build our CityTabCarousel; for our example, we will create a dummy list of pages with our cities from the previous project:
    @Composable
    fun CityTabCarousel(
        pages: MutableList<String> = arrayListOf(
            "Spain",
            "New York",
            "Tokyo",
            "Switzerland",
            "Singapore",
            "Paris" )) {. . .}
  3. We will need to change the color of the button based on the state, and to do this; we need to use LocalContext, which provides the context we can use. We will also need to create a var pagerState = rememberPagerState(), which will remember our pager state, and finally, when clicked, we will need to move to the next city in our pager, which will be very helpful. Hence, go ahead and add the following to the CityTabCarousel composable function:
    val context = LocalContext.current
    var pagerState = rememberPagerState()
    val coroutineScope = rememberCoroutineScope()
  4. Now, let’s create the Column element and add our ScrollableTabRow() composable function:
    Column {
        ScrollableTabRow(
            selectedTabIndex = pagerState.currentPage,
            indicator = { tabPositions ->
                TabRowDefaults.Indicator(...)
            },
            edgePadding = 0.dp,
            backgroundColor = Color(
                context.resources.getColor(R.color.white,
                    null)),
        ) {
            pages.forEachIndexed { index, title ->
                val isSelected =
                    pagerState.currentPage == index
                TabHeader(
                    title,
                    isSelected,
                    onClick = { coroutineScope.launch {
                    pagerState.animateScrollToPage(index)
                    } },
                )
            }
        }
  5. Add Text() and TabHeader() for HorizontalPager:
        HorizontalPager(
            count = pages.size,
            state = pagerState,
            modifier = Modifier
                .fillMaxWidth()
                .fillMaxHeight()
                .background(Color.White)
        ) { page ->
            Text(
                text = "Display City Name:
                    ${pages[page]}",
                modifier = Modifier.fillMaxWidth(),
                style = TextStyle(
                    textAlign = TextAlign.Center
                )
            )
        }
  6. Please download the entire code for this recipe by following the link provided in the Technical requirements section to add all the required code. Finally, run the @Preview function, and your app should look like Figure 2.8.
Figure 2.8 – Tabs with cities

Figure 2.8 – Tabs with cities

How it works…

Accompanist comes with some significant libraries – for example, System UI Controller, AppCompact Compose Theme Adapter, Material Theme Adapter, Pager, Drawable Painter, and Flow Layouts, just to mention a few.

The ScrollableTabRow() that we use inside Column in the CityTabCarousel function contains a row of tabs and helps display an indicator underneath the currently focused or selected tab. In addition, as the name suggests, it enables scrolling and you do not have to implement further scrolling tooling. It also places its tab offsets at the starting edge, and you can quickly scroll tabs that are off-screen, as you will see when you run the @Preview function and play around with it.

When we invoke remember(), in Compose, this means we keep any value consistent across recomposition. Compose provides this function to help us store single objects in memory. When we trigger our application to run, remember() stores the initial value. As the word means, it simply retains the value and returns the stored value so that the composable function can use it.

Furthermore, whenever the stored value changes, you can update it, and the remember() function will keep it. The next time we trigger another run in our app and recomposition occurs, the remember() function will provide the latest stored value.

You will also notice our MutableList<String> is indexed at each position, and we do this to check which is selected. It is within this Lambda that we call TabHeader and showcase the selected tab pages. forEachIndexed performs the given action on each element, providing a sequential index of elements. We also ensure when a user clicks on a specific tab, we are on the right page:

onClick = { coroutineScope.launch { pagerState.animateScrollToPage(index) } }

HorizontalPager is a horizontally scrolling layout that allows our users to flip between items from left to right. It takes in several inputs, but we supply it with the count, state, and modifier to decorate it in our use case. In the Lambda, we display text – in our example, showing which page we are on, which helps when navigating, as shown in Figure 2.9:

Figure 2.9 – HorizontalPager

Figure 2.9 – HorizontalPager

Our TabHeader composable function has a Box(); a box in Jetpack Compose will always size itself to fit the content, and this is subject to the specified constraints. In our example, we decorate our Box with the selectable modifier, which configures components to be selectable as part of a mutually exclusive group, allowing each item to be selected only once at any given time.

Important note

Ensure your target and compile SDK targets 33. In addition, you will notice that most Accompanist’s libraries are experimental, which means they can change. There is debate on whether to use this in your production, so you should always consult your team on these APIs. To see the entire list of libraries supported by Accompanist, you can follow this link: https://github.com/google/accompanist.

You have been reading a chapter from
Modern Android 13 Development Cookbook
Published in: Jul 2023 Publisher: Packt ISBN-13: 9781803235578
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at €14.99/month. Cancel anytime}