Skip to content

Instantly share code, notes, and snippets.

@ltvu93
Last active April 23, 2021 10:28
Show Gist options
  • Save ltvu93/0d098730874a66e776b0a01ffa15bd8c to your computer and use it in GitHub Desktop.
Save ltvu93/0d098730874a66e776b0a01ffa15bd8c to your computer and use it in GitHub Desktop.
Custom tab bar with animation in Jetpack Compose
package com.example.testcompose
import androidx.compose.animation.animateColorAsState
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.BiasAlignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
@Composable
fun CustomTabBarDemo() {
var currentIndex by remember { mutableStateOf(0) }
CustomTabBar(
modifier = Modifier.padding(16.dp),
onTap = { index -> currentIndex = index },
index = currentIndex,
labels = listOf("Main", "Detail", "Social"),
)
}
@Composable
fun CustomTabBar(
modifier: Modifier = Modifier,
onTap: (Int) -> Unit,
index: Int,
labels: List<String>,
) {
Box(
modifier
.fillMaxWidth()
.height(50.dp)
.border(width = 1.dp, color = Color.Gray, shape = RoundedCornerShape(5.dp)),
) {
val currentIndexHorizontalBias by animateFloatAsState(-1 + (index.toFloat() / (labels.size - 1)) * 2)
// val currentIndexHorizontalBias by animateFloatAsState(
// MathUtils.lerp(
// -1f,
// 1f,
// index.toFloat() / (labels.size - 1)
// )
// )
Box(
Modifier
.fillMaxWidth(1f / labels.size)
.fillMaxSize()
.align(BiasAlignment(currentIndexHorizontalBias, 0f))
.background(color = MaterialTheme.colors.primary, shape = RoundedCornerShape(5.dp)),
)
Row(
modifier = Modifier.fillMaxHeight(),
verticalAlignment = Alignment.CenterVertically,
) {
labels.forEachIndexed { i, label ->
val color by animateColorAsState(if (i == index) MaterialTheme.colors.onPrimary else MaterialTheme.colors.onBackground)
Box(
modifier = Modifier
.weight(1f)
.fillMaxHeight()
.clickable { onTap(i) },
) {
Text(
text = label,
modifier = Modifier.align(Alignment.Center),
textAlign = TextAlign.Center,
color = color,
)
}
}
}
}
}
@ltvu93
Copy link
Author

ltvu93 commented Apr 23, 2021

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment