Jetpack Compose Reducing internal padding of Tabs
Asked Answered
Y

5

12

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)) }
  }
}
Yonyona answered 27/8, 2021 at 7:10 Comment(0)
W
9

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()
Waiter answered 27/8, 2021 at 9:23 Comment(4)
Thanks a lot. You are right. May be I need to go for a custom Tab RowYonyona
It is very strange that out of the box we cannot set the desired tab width. Your solution is still relevant for 1.2.0-rc03 version of ComposeLatishalatitude
How do you copy and paste the ScrollableTabRow when it uses a private TabSlots class and private ScrollablTabData?Retention
You will need to copy all the needed classes, unfortunately. Unless at some point you can comment out some things.Waiter
A
6

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()
}
Amphibolite answered 2/9, 2022 at 9:36 Comment(4)
Can you tell me how to use it?Gynophore
@Gynophore Just run this code once, for example in your main activity onCreate (or application). This will change the value of ScrollableTabRowMinimumTabWidth in the whole app. Be aware that an update of material lib might silently break this workaround.Katzman
I used this method, effective, but not the smallest width, and it became a fixed width. Do I need to modify the value in the value of } .set (this, 10F)?Gynophore
@Gynophore I'm not sure to understand your need, with 0f, the tab will fit the text or the indicator. With 10f, it does the same with a min of 10dp. The default min width is 90dp android.googlesource.com/platform/frameworks/support/+/refs/…Katzman
N
2

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)

Not answered 8/4, 2022 at 5:52 Comment(0)
L
1

To remove outer paddings and add inner, use this code:

ScrollableTabRow(
    edgePadding = -5.dp,
) {
    tabs.forEachIndexed { index, title ->
        Tab(
            modifier = Modifier
                .padding(horizontal = 5.dp),
Larina answered 24/4, 2024 at 8:34 Comment(0)
N
0

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

Neopythagoreanism answered 22/1, 2024 at 23:13 Comment(1)
Of course, it doesn't work. Could you send more code?Larina

© 2022 - 2025 — McMap. All rights reserved.