Jetpack Compose Reducing internal padding of Tabs

6.4k Views Asked by At

I want to reduce padding of a single tab. Following image shows what I want:

1

What I am getting:

2

I am currently using the "accompanist-pager" and "accompanist-pager-indicators" with version 0.16.0.

Code:

@Composable
fun Tabs(tabNames: List<String>, pagerState: PagerState, scrollToPage: (Int) -> Unit) {
  TabRow(
    selectedTabIndex = pagerState.currentPage,
    backgroundColor = Color.White,
    contentColor = Color.Black,
    divider = {
      TabRowDefaults.Divider(
        thickness = 4.dp
      )
    },
    indicator = { tabPositions ->
      TabRowDefaults.Indicator(
        modifier = Modifier.customTabIndicatorOffset(tabPositions[pagerState.currentPage]),
        height = 4.dp,
        color = EmeraldTheme.colors.primary
      )
    }
  ) {
    tabNames.forEachIndexed { index, name ->
      Tab(
        text = {
          Text(
            text = name,
            maxLines = 1,
            style = globalSearchDefaultTextStyle,
            fontWeight = if (pagerState.currentPage == index) FontWeight.Bold else FontWeight.Normal,
            color = if (pagerState.currentPage == index) EmeraldColor.Black100 else colorResource(globalSearchR.color.darkGrey20),
          )
        },
        selected = pagerState.currentPage == index,
        onClick = {
          scrollToPage(index)
        }
      )
    }
    Row { Spacer(Modifier.weight(1f, true)) }
  }
}
4

There are 4 best solutions below

4
Bartek Lipinski On BEST ANSWER

With the current version of TabRow (or ScrollableTabRow) you will not be able to do it. You will need to create your own TabRow composable.

Also, you should probably use a ScrollableTabRow instead of TabRow because TabRow evenly distributes the entire available width for its Tabs. So the content padding for that doesn't matter that much.

You can pretty much copy-paste the entire code for ScrollableTabRow, but modify the bit that sets up the tabConstraints.

It should no longer use the minTabWidth:

val minTabWidth = ScrollableTabRowMinimumTabWidth.roundToPx()
0
Zepta B On

Custom tab is the way to go.

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.size
import androidx.compose.material.Tab
import androidx.compose.material.Text

Tab(selected, onClick) {
    Column(
        Modifier.padding(10.dp).height(50.dp).fillMaxWidth(),
        verticalArrangement = Arrangement.SpaceBetween
    ) {
        Box(
            Modifier.size(10.dp)
                .align(Alignment.CenterHorizontally)
                .background(color = if (selected) Color.Red else Color.White)
        )
        Text(
            text = title,
            style = MaterialTheme.typography.body1,
            modifier = Modifier.align(Alignment.CenterHorizontally)
        )
    }
}

https://developer.android.com/reference/kotlin/androidx/compose/material/package-summary#Tab(kotlin.Boolean,kotlin.Function0,androidx.compose.ui.Modifier,kotlin.Boolean,androidx.compose.foundation.interaction.MutableInteractionSource,androidx.compose.ui.graphics.Color,androidx.compose.ui.graphics.Color,kotlin.Function1)

4
Rémi Latapy On

You can use java reflection to change the value of ScrollableTabRowMinimumTabWidth. And you can upvote here -> https://issuetracker.google.com/issues/226665301

try {
    Class
        .forName("androidx.compose.material3.TabRowKt")
        .getDeclaredField("ScrollableTabRowMinimumTabWidth").apply {
            isAccessible = true
        }.set(this, 0f)
} catch (e: Exception) {
    e.printStackTrace()
}
0
Ifeanyi Opara On

A quick way you can solve this setting a fixed width in the Modifier