androidandroid-jetpack-composelandscape-portraitandroid-scrollable-tabs

How to make scrollable Tabrow fill max width in landscape mode in Jetpack Compose?


When changing screen orientation to landscape mode, the Scrollable Tabrow only occupies half of the screen, as in this image. I want to make it fill max width of the screen.

As of the following code, I've made the scrollable tabrow fill max width.

Image

ScrollableTabRow(
        selectedTabIndex = pagerState.currentPage,
        edgePadding = 0.dp,
        divider = {
            Spacer(modifier = Modifier.height(1.dp))
        },
        indicator = { tabPositions ->
            SecondaryIndicator(
                modifier = Modifier.customTabIndicatorOffset(
                    currentTabPosition = tabPositions[pagerState.currentPage],
                    tabWidth = tabWidths[pagerState.currentPage]
                ),
                color = MaterialTheme.colorScheme.primary
            )
        },


        modifier = Modifier
            .fillMaxWidth()
            .background(MaterialTheme.customColorsPalette.mainAppBar)
            .wrapContentHeight()
    ) {
        tabData.forEachIndexed { index, title ->
            Tab(
                modifier = Modifier.background(MaterialTheme.customColorsPalette.mainAppBar),
                selected = pagerState.currentPage == index, onClick = {
                scope.launch {
                    pagerState.animateScrollToPage(index)
                }
            },
                text = {
                    Text(
                        text = title,
                        onTextLayout = { textLayoutResult ->
                            tabWidths[index] =
                                with(density) { textLayoutResult.size.width.toDp() }
                        }
                    )
                }
            )
        }
    }

Solution

  • For making it full width you have to use TabRow which is not scrollable and tabs are created with equal weight making it fill the width. However you have to be sure that in landscape all items will fit into TabRow.

    I updated your code:

    @Composable
    fun CustomTabsRow() {
        val configuration = LocalConfiguration.current
        val tabData = remember {
            listOf("Events", "Details", "Lineups", "Stats", "Endings")
        }
        val scope = rememberCoroutineScope()
        val pagerState = rememberPagerState {
            tabData.size
        }
    
        if (configuration.orientation == Configuration.ORIENTATION_LANDSCAPE) {
            TabRow(
                selectedTabIndex = pagerState.currentPage,
                divider = {
                    Spacer(modifier = Modifier.height(1.dp))
                },
                indicator = { tabPositions ->
                    SecondaryIndicator(
                        modifier = Modifier.customTabIndicatorOffset(
                            currentTabPosition = tabPositions[pagerState.currentPage],
                            tabWidth = tabWidths[pagerState.currentPage]
                        ),
                        color = MaterialTheme.colorScheme.primary
                    )
                },
                modifier = Modifier
                    .fillMaxWidth()
                    .background(MaterialTheme.customColorsPalette.mainAppBar)
                    .wrapContentHeight()
            ) {
                tabData.forEachIndexed { index, title ->
                    Tab(
                        modifier = Modifier.background(MaterialTheme.customColorsPalette.mainAppBar),
                        selected = pagerState.currentPage == index, onClick = {
                            scope.launch {
                                pagerState.animateScrollToPage(index)
                            }
                        },
                        text = {
                            Text(
                                text = title,
                                onTextLayout = { textLayoutResult ->
                                    tabWidths[index] =
                                        with(density) { textLayoutResult.size.width.toDp() }
                                }
                            )
                        }
                    )
                }
            }
        } else {
            ScrollableTabRow(
                selectedTabIndex = pagerState.currentPage,
                edgePadding = 0.dp,
                divider = {
                    Spacer(modifier = Modifier.height(1.dp))
                },
                indicator = { tabPositions ->
                    SecondaryIndicator(
                        modifier = Modifier.customTabIndicatorOffset(
                            currentTabPosition = tabPositions[pagerState.currentPage],
                            tabWidth = tabWidths[pagerState.currentPage]
                        ),
                        color = MaterialTheme.colorScheme.primary
                    )
                },
                modifier = Modifier
                    .fillMaxWidth()
                    .background(MaterialTheme.customColorsPalette.mainAppBar)
                    .wrapContentHeight()
            ) {
                tabData.forEachIndexed { index, title ->
                    Tab(
                        modifier = Modifier.background(MaterialTheme.customColorsPalette.mainAppBar),
                        selected = pagerState.currentPage == index, onClick = {
                            scope.launch {
                                pagerState.animateScrollToPage(index)
                            }
                        },
                        text = {
                            Text(
                                text = title,
                                onTextLayout = { textLayoutResult ->
                                    tabWidths[index] =
                                        with(density) { textLayoutResult.size.width.toDp() }
                                }
                            )
                        }
                    )
                }
            }
        }
    }