This is the second article of a series about Jetpack Compose.
Posts in this series :
Resources:
Our Jetpack Compose Stories !
Let's warm up by using our progress bar in a typical Instagram's like screen.
++pre>++code class="has-line-data" data-line-start="30" data-line-end="77">@Composable
fun InstagramScreen() {
// We will hardcode those parameter for now.
val steps = 5;
val currentStep = 2;
val isPressed = remember { mutableStateOf(false) }
val goToPreviousScreen = {}
val goToNextScreen = {}
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier =
Modifier
.background(
Brush.linearGradient( // (1)
colors = listOf(GreenLemon, GreenLeaves, BlueSea), // (2)
start = Offset.Zero, end = Offset.Infinite
)
)
) {
InstagramSlicedProgressBar(steps, currentStep, isPressed.value, goToNextScreen)
Column(
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center,
modifier = Modifier.weight(1f)
) {
Text(
text = "Hello world !",
style = Typography.h1,
color = Color.White
)
Spacer(modifier = Modifier.height(8.dp))
Text(
text = "Tap or wait to go to the next screen",
style = Typography.body1,
color = Color.White
)
Spacer(modifier = Modifier.height(8.dp))
Text(
text = "?",
style = Typography.body1,
color = Color.White
)
}
}
}
++/code>++/pre>
Adding gestures to this screen is not very complicated. Jetpack Compose ++code>pointerInput++/code> modifier is very handful in this situation :
++pre>++code class="has-line-data" data-line-start="94" data-line-end="135">@Composable
fun InstagramScreen() {
// We will hardcode those parameter for now.
val steps = 5;
val currentStep = 2;
val isPressed = remember { mutableStateOf(false) }
val goToPreviousScreen = {}
val goToNextScreen = {}
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier =
Modifier
.background(
...
).pointerInput(Unit) { // (1)
val maxWidth = this.size.width // (2)
detectTapGestures(
onPress = { // (3)
val pressStartTime = System.currentTimeMillis()
isPressed.value = true
this.tryAwaitRelease() // (4)
val pressEndTime = System.currentTimeMillis()
val totalPressTime = pressEndTime - pressStartTime // (5)
if (totalPressTime < 200) {
val isTapOnRightTwoTiers = (it.x > (maxWidth / 4)) // (6)
if (isTapOnRightTwoTiers) {
goToNextScreen()
} else {
goToPreviousScreen()
}
}
isPressed.value = false
},
)
}
) {
...
}
}
++/code>++/pre>
We can easily set up a navigation with the ++code>androidx.navigation:navigation-compose++/code> package.
++pre>++code class="has-line-data" data-line-start="160" data-line-end="162"> implementation("androidx.navigation:navigation-compose:2.4.0-alpha03")
++/code>++/pre>
Here is our entry point :
++pre>++code class="has-line-data" data-line-start="166" data-line-end="186">@Composable
fun Navigation() {
val navController = rememberNavController()
NavHost(navController = navController, startDestination = "instagram/{steps}/{currentStep}") { // (1)
composable( // (2)
"instagram/{steps}/{currentStep}",
arguments = listOf(
navArgument("steps") { type = NavType.IntType; defaultValue = 8 }, // (3)
navArgument("currentStep") { type = NavType.IntType; defaultValue = 1 }, // (4)
)
) { backStackEntry -> // (5)
InstagramScreen(
navController,
backStackEntry.arguments!!.getInt("steps"),
backStackEntry.arguments!!.getInt("currentStep"),
)
}
}
}
++/code>++/pre>
Remember our hardcoded values ? Let's change those :
++pre>++code class="has-line-data" data-line-start="196" data-line-end="208">@Composable
fun InstagramScreen(navController: NavController, steps: Int, currentStep: Int) {
val goToNextScreen = {
if (currentStep + 1 <= steps) navController.navigate("instagram/$steps/${currentStep + 1}")
}
val goToPreviousScreen = {
if (currentStep - 1 > 0) navController.navigate("instagram/$steps/${currentStep - 1}")
}
...
}
++/code>++/pre>
Here you go !
The final result is here :