1

I want to modify the width of each Tab, but I can't do it. I know it can be customized, but I just want to modify the width, is there any way?

enter image description here


@OptIn(ExperimentalPagerApi::class)
@Preview
@Composable
fun TabPreviewTest() {

    val scope = rememberCoroutineScope()
    val colorScheme = MaterialTheme.colorScheme
    val pagerState = rememberPagerState(initialPage = 1)
    val titleList = rememberSaveable { mutableListOf("关注", "推荐", "美食", "护肤", "穿搭", "健身塑形", "数码") }

    ScrollableTabRow(
        selectedTabIndex = pagerState.currentPage,
        containerColor = colorScheme.surface.copy(0.94f),
        contentColor = colorScheme.primary,
        divider = { DividerView(start = 0) }) {
        titleList.forEachIndexed { index, title ->
            Tab(text = { Text(text = title) },
                selected = pagerState.currentPage == index,
                selectedContentColor = colorScheme.primary,
                unselectedContentColor = colorScheme.gray,
                onClick = {
                    scope.launch { pagerState.scrollToPage(index) }
                    //onClick(index)
                },
                modifier = Modifier.padding(0.dp).width(0.dp)
            )
        }
    }
}



gaohomway
  • 2,132
  • 1
  • 20
  • 37

1 Answers1

0

You can change Tab width when it's above 90.dp since in source code it's measured with Constraints with minimum 90.dp

private val ScrollableTabRowMinimumTabWidth = 90.dp

Unfortunately they added this as a fixed value so you need to copy source code and do the change indicated below.

@Composable
@UiComposable
fun ScrollableTabRow(
    selectedTabIndex: Int,
    modifier: Modifier = Modifier,
    backgroundColor: Color = MaterialTheme.colors.primarySurface,
    contentColor: Color = contentColorFor(backgroundColor),
    edgePadding: Dp = TabRowDefaults.ScrollableTabRowPadding,
    indicator: @Composable @UiComposable
        (tabPositions: List<TabPosition>) -> Unit = @Composable { tabPositions ->
            TabRowDefaults.Indicator(
                Modifier.tabIndicatorOffset(tabPositions[selectedTabIndex])
            )
        },
    divider: @Composable @UiComposable () -> Unit =
        @Composable {
            TabRowDefaults.Divider()
        },
    tabs: @Composable @UiComposable () -> Unit
) {
    Surface(
        modifier = modifier,
        color = backgroundColor,
        contentColor = contentColor
    ) {
        val scrollState = rememberScrollState()
        val coroutineScope = rememberCoroutineScope()
        val scrollableTabData = remember(scrollState, coroutineScope) {
            ScrollableTabData(
                scrollState = scrollState,
                coroutineScope = coroutineScope
            )
        }
        SubcomposeLayout(
            Modifier.fillMaxWidth()
                .wrapContentSize(align = Alignment.CenterStart)
                .horizontalScroll(scrollState)
                .selectableGroup()
                .clipToBounds()
        ) { constraints ->
            val minTabWidth = ScrollableTabRowMinimumTabWidth.roundToPx()
            val padding = edgePadding.roundToPx()

           //  This is the minimum size it's measured with
            val tabConstraints = constraints.copy(minWidth = minTabWidth)

         // Rest of the code
}

If you copy-paste source code and change minimumTabWidth to 0 you will be able to assign any width modifier.

I posted similar answer here with demo here how to change and the value and use it

Reduce Spacing between Scrollable tabs in compose

Thracian
  • 43,021
  • 16
  • 133
  • 222
  • Thank you for your answer, there are too many places to modify, I finally solved it through the answer of https://stackoverflow.com/a/73580585/4218245 – gaohomway Feb 02 '23 at 11:06
  • Reflection is probably the worst way to solve any ui related issue. You should better wait for the issue being closed on Google side if you don't want to modify existing code. However the thing to modify is only one line. You should copy-paste source code and change one line only. I posted whole code for it to be easy to try – Thracian Feb 02 '23 at 11:15
  • Yes, I don't know about reflection, but I feel that it is not the final solution to this problem, and your train of thought is right. – gaohomway Feb 02 '23 at 11:17
  • Reflection is getting a private parameter by name and using it in your code to access it which could easily change and crash your app – Thracian Feb 02 '23 at 11:18
  • Do you have an easier way to solve this – gaohomway Feb 02 '23 at 11:19
  • As i posted in answer copy paste whole code and change `private val ScrollableTabRowMinimumTabWidth = 90.dp` to 0.dp and when the issue is solved use the one from Google. The answer you posted does this but it accesses private parameter. Using reflection for this kind of ui operations is risky because google might change param name and your app might crash, for the answer you posted since it's inside try-catch nothing would happen if they change parameter name. Instead of this copy-pasting source code is the safer behavior. I'm only suggesting an alternative, you can pick whichever suits best – Thracian Feb 02 '23 at 11:37
  • Okay, thank you very much, I will use your method first, and look forward to the official solution – gaohomway Feb 02 '23 at 12:02
  • Do you ever test your code before posting @Thracian ? I don't think a single developer/person can get help from this solution. It's a mess. No imported packages name available in this solution and there are plenty of keywords missing when someone paste this code to file. – Kishan Solanki Aug 05 '23 at 06:26
  • Have you checked out any of my answers? I posted over 570 answers and i check and test them and post not only single solutions and with alternatives. And in how many answer in stackoverflow did you see exports? You will need to copy-paste source code of TabRow and change 90.dp to another value. And if you are not able to export code from copy paste source code you can ask kindly about it. Another answer that shows how to use it https://stackoverflow.com/a/76533630/5457853 – Thracian Aug 05 '23 at 06:32