What You'll Learn
Predictive Back (predictive back gesture, custom animation, Navigation integration, BottomSheet support) explained.
What is Predictive Back?
Android 14 predictive back gesture. Shows preview during back gesture, user can cancel before completion.
<!-- AndroidManifest.xml -->
<application
android:enableOnBackInvokedCallback="true">
</application>
Basic Support
// Compose Navigation auto-supports Predictive Back
@Composable
fun AppNavigation() {
val navController = rememberNavController()
NavHost(
navController = navController,
startDestination = "home",
// Predictive Back animation auto-applied
enterTransition = { slideIntoContainer(AnimatedContentTransitionScope.SlideDirection.Start) },
exitTransition = { slideOutOfContainer(AnimatedContentTransitionScope.SlideDirection.Start) },
popEnterTransition = { slideIntoContainer(AnimatedContentTransitionScope.SlideDirection.End) },
popExitTransition = { slideOutOfContainer(AnimatedContentTransitionScope.SlideDirection.End) }
) {
composable("home") { HomeScreen(navController) }
composable("detail") { DetailScreen() }
}
}
Custom Predictive Back
@Composable
fun PredictiveBackSheet(
onDismiss: () -> Unit,
content: @Composable () -> Unit
) {
var progress by remember { mutableFloatStateOf(0f) }
PredictiveBackHandler(enabled = true) { backEvent ->
backEvent.collect { event ->
progress = event.progress
}
onDismiss()
progress = 0f
}
val scale = 1f - (progress * 0.1f)
val alpha = 1f - progress
Box(
Modifier
.fillMaxSize()
.graphicsLayer {
scaleX = scale
scaleY = scale
this.alpha = alpha
}
) {
content()
}
}
BackHandler (Legacy Back Handling)
@Composable
fun EditScreen(onNavigateBack: () -> Unit) {
var hasUnsavedChanges by remember { mutableStateOf(false) }
var showDialog by remember { mutableStateOf(false) }
BackHandler(enabled = hasUnsavedChanges) {
showDialog = true
}
if (showDialog) {
AlertDialog(
onDismissRequest = { showDialog = false },
title = { Text("Discard changes?") },
confirmButton = {
TextButton(onClick = { onNavigateBack() }) { Text("Discard") }
},
dismissButton = {
TextButton(onClick = { showDialog = false }) { Text("Cancel") }
}
)
}
Column(Modifier.padding(16.dp)) {
OutlinedTextField(
value = "",
onValueChange = { hasUnsavedChanges = true },
label = { Text("Input") }
)
}
}
ModalBottomSheet Support
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun PredictiveBackBottomSheet() {
var showSheet by remember { mutableStateOf(false) }
val sheetState = rememberModalBottomSheetState()
Button(onClick = { showSheet = true }) { Text("Open Sheet") }
if (showSheet) {
ModalBottomSheet(
onDismissRequest = { showSheet = false },
sheetState = sheetState
// Material3 ModalBottomSheet auto-supports Predictive Back
) {
Column(Modifier.padding(16.dp)) {
Text("BottomSheet Content")
Spacer(Modifier.height(32.dp))
}
}
}
}
Summary
| Feature | Implementation |
|---|---|
| Enable | enableOnBackInvokedCallback=true |
| Navigation | Auto-support (animation included) |
| Custom | PredictiveBackHandler |
| Legacy back | BackHandler |
| BottomSheet | Material3 auto-support |
-
enableOnBackInvokedCallbackenables Predictive Back - Compose Navigation auto-applies preview animation
-
PredictiveBackHandlerfor custom animation - Most Material3 components auto-support
Ready-Made Android App Templates
8 production-ready Android app templates with Jetpack Compose, MVVM, Hilt, and Material 3.
Browse templates → Gumroad
Top comments (0)