R0ck
R0ck

Reputation: 499

BottomNavigationItems padding

Is there any way to remove this padding from the BottomNavigationItem?

Image

If I have very large text, I have to use ResponsiveText to manage this, but that's not what I intended. What I need is that it doesn't have that side padding/margin, both on the left and on the right, in order to occupy as much space as possible.

My code:

@Composable
fun BottomNavBar(
    backStackEntryState: State<NavBackStackEntry?>,
    navController: NavController,
    bottomNavItems: List<NavigationItem>
) {
    BottomNavigation(
        backgroundColor = DarkGray.copy(alpha = 0.6f),
        elevation = Dimen0,
        modifier = Modifier
            .padding(Dimen10, Dimen20, Dimen10, Dimen20)
            .clip(RoundedCornerShape(Dimen13, Dimen13, Dimen13, Dimen13))
    ) {
        bottomNavItems.forEach { item ->
            val isSelected = item.route == backStackEntryState.value?.destination?.route

            BottomNavigationItem(
                icon = {
                    Icon(
                        painter = painterResource(id = item.icon.orZero()),
                        contentDescription = stringResource(id = item.title)
                    )
                },
                label = {
                    ResponsiveText(
                        text = stringResource(id = item.title),
                        textStyle = TextStyle14,
                        maxLines = 1
                    )
                },
                selectedContentColor = Color.White,
                unselectedContentColor = Color.White,
                alwaysShowLabel = true,
                selected = isSelected,
                onClick = {
                    navController.navigate(item.route) {
                        navController.graph.startDestinationRoute?.let { route ->
                            popUpTo(route = route) {
                                saveState = true
                            }
                        }

                        launchSingleTop = true
                        restoreState = true
                    }
                },
                modifier = if (isSelected) {
                    Modifier
                        .clip(RoundedCornerShape(Dimen13, Dimen13, Dimen13, Dimen13))
                        .background(color = DarkGray)
                } else {
                    Modifier.background(color = Color.Unspecified)
                }
            )
        }
    }
}

Upvotes: 10

Views: 2941

Answers (2)

MisseMask
MisseMask

Reputation: 459

Another solution is to wrap the label in a BoxWithConstraints and draw outside of it:

BottomNavigationItem(
    label = {
        /**
         * Because of [BottomNavigationItemHorizontalPadding] (12.dp), we need to
         * think (and draw) outside the box.
         */
        BoxWithConstraints {
            Text(
                modifier = Modifier
                    .wrapContentWidth(unbounded = true)
                    .requiredWidth(maxWidth + 24.dp), // 24.dp = the padding * 2
                text = "Centered text and clipped at the end if too long",
                softWrap = false,
                textAlign = TextAlign.Center
            )
        }
    },
    ...
)

To get a little bit of padding, you can set requiredWidth(maxWidth + 18.dp).

With this solution, you don't need to copy the entire BottomNavigation :)

Upvotes: 12

tasjapr
tasjapr

Reputation: 1220

Apparently this is currently (I am using compose version '1.2.0-rc03') not possible when using BottomNavigation, as there is padding set for each element in these lines:

.padding(horizontal = BottomNavigationItemHorizontalPadding)

Here is what is said about this value:

/**
 * Padding at the start and end of a [BottomNavigationItem]
 */
private val BottomNavigationItemHorizontalPadding = 12.dp

[Solution]

Just copy BottomNavigation from androidx and remov this line:

.padding(horizontal = BottomNavigationItemHorizontalPadding)

However, it is necessary that the first and last elements still have padding, so add the innerHorizontalPaddings parameter to the your CustomBottomNavigation constructor

There are a few more changes, you can see the full code of my CustomBottomNavigation here

Example of usage:

CustomBottomNavigation(
...,
innerHorizontalPaddings = 12.dp
) {
    items.forEach { item ->
        BottomNavigationItem(
            icon = {
                Icon(...)
            },
            label = {
                Text(
                    ...
                    softWrap = false,
                    overflow = TextOverflow.Ellipsis,
                    modifier = Modifier.padding(horizontal = 2.dp)
                )
            },
            ...
        )
    }
}

Upvotes: 3

Related Questions