From 45d1f1eee613d57b441179f8b6d94b1bdaa92eee Mon Sep 17 00:00:00 2001 From: Tram Bui Date: Thu, 7 Nov 2024 14:53:25 -0800 Subject: [PATCH 1/4] add in predictive back snippets --- .../predictiveback/PredictiveBackSnippets.kt | 142 ++++++++++++++++++ 1 file changed, 142 insertions(+) create mode 100644 compose/snippets/src/main/java/com/example/compose/snippets/predictiveback/PredictiveBackSnippets.kt diff --git a/compose/snippets/src/main/java/com/example/compose/snippets/predictiveback/PredictiveBackSnippets.kt b/compose/snippets/src/main/java/com/example/compose/snippets/predictiveback/PredictiveBackSnippets.kt new file mode 100644 index 00000000..96392f88 --- /dev/null +++ b/compose/snippets/src/main/java/com/example/compose/snippets/predictiveback/PredictiveBackSnippets.kt @@ -0,0 +1,142 @@ +package com.example.compose.snippets.predictiveback + +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.navigation.compose.NavHost +import androidx.navigation.compose.rememberNavController +import androidx.navigation.NavHostController +import androidx.compose.animation.scaleOut +import androidx.compose.ui.graphics.TransformOrigin +import androidx.compose.animation.EnterTransition +import android.os.SystemClock +import androidx.activity.compose.PredictiveBackHandler +import androidx.compose.ui.unit.dp +import androidx.compose.animation.core.Animatable +import androidx.navigation.compose.composable +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.material3.Surface +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.setValue +import androidx.compose.ui.geometry.Offset +import androidx.compose.ui.input.pointer.util.VelocityTracker +import androidx.compose.ui.platform.LocalDensity +import kotlin.coroutines.cancellation.CancellationException + + +@Composable +private fun PredictiveBackOverrideExit( + modifier: Modifier, +) { + val navController = rememberNavController() + + // [START android_compose_predictiveback_navhost] + NavHost( + navController = navController, + startDestination = "home", + popExitTransition = { + scaleOut( + targetScale = 0.9f, + transformOrigin = TransformOrigin(pivotFractionX = 0.5f, pivotFractionY = 0.5f) + ) + }, + popEnterTransition = { + EnterTransition.None + }, + modifier = modifier, + ) + // [END android_compose_predictiveback_navhost] + { + composable("home") { + HomeScreen( + modifier = modifier, + navController = navController, + ) + } + composable("settings") { + SettingsScreen( + modifier = modifier, + navController = navController, + ) + } + } +} + +@Composable +private fun HomeScreen( + modifier: Modifier = Modifier, navController: NavHostController +) { + +} + +@Composable +private fun SettingsScreen( + modifier: Modifier = Modifier, navController: NavHostController +) { + +} + +@Composable +private fun PredictiveBackHandlerManualProgress() { + + Surface( + modifier = Modifier.fillMaxSize() + ) { + var drawerState by remember { + mutableStateOf(DrawerState.Closed) + } + + val translationX = remember { + Animatable(0f) + } + + val drawerWidth = with(LocalDensity.current) { + DrawerWidth.toPx() + } + translationX.updateBounds(0f, drawerWidth) + + val coroutineScope = rememberCoroutineScope() + + suspend fun closeDrawer(velocity: Float = 0f) { + translationX.animateTo(targetValue = 0f, initialVelocity = velocity) + drawerState = DrawerState.Closed + } + suspend fun openDrawer(velocity: Float = 0f) { + translationX.animateTo(targetValue = drawerWidth, initialVelocity = velocity) + drawerState = DrawerState.Open + } + + val velocityTracker = remember { + VelocityTracker() + } + + // [START android_compose_predictivebackhandler] + PredictiveBackHandler(drawerState == DrawerState.Open) { progress -> + try { + progress.collect { backEvent -> + val targetSize = (drawerWidth - (drawerWidth * backEvent.progress)) + translationX.snapTo(targetSize) + velocityTracker.addPosition( + SystemClock.uptimeMillis(), + Offset(backEvent.touchX, backEvent.touchY) + ) + } + closeDrawer(velocityTracker.calculateVelocity().x) + } catch (e: CancellationException) { + openDrawer(velocityTracker.calculateVelocity().x) + } + velocityTracker.resetTracking() + } + // [END android_compose_predictivebackhandler] + + } +} + +private enum class DrawerState { + Open, + Closed +} + +private val DrawerWidth = 300.dp \ No newline at end of file From 4f28f0636eb27706a2fd59d99c98a7b1a919bf30 Mon Sep 17 00:00:00 2001 From: trambui09 Date: Thu, 7 Nov 2024 22:56:18 +0000 Subject: [PATCH 2/4] Apply Spotless --- .../predictiveback/PredictiveBackSnippets.kt | 50 ++++++++++++------- 1 file changed, 32 insertions(+), 18 deletions(-) diff --git a/compose/snippets/src/main/java/com/example/compose/snippets/predictiveback/PredictiveBackSnippets.kt b/compose/snippets/src/main/java/com/example/compose/snippets/predictiveback/PredictiveBackSnippets.kt index 96392f88..ff1fc6cf 100644 --- a/compose/snippets/src/main/java/com/example/compose/snippets/predictiveback/PredictiveBackSnippets.kt +++ b/compose/snippets/src/main/java/com/example/compose/snippets/predictiveback/PredictiveBackSnippets.kt @@ -1,31 +1,46 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package com.example.compose.snippets.predictiveback -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.navigation.compose.NavHost -import androidx.navigation.compose.rememberNavController -import androidx.navigation.NavHostController -import androidx.compose.animation.scaleOut -import androidx.compose.ui.graphics.TransformOrigin -import androidx.compose.animation.EnterTransition import android.os.SystemClock import androidx.activity.compose.PredictiveBackHandler -import androidx.compose.ui.unit.dp +import androidx.compose.animation.EnterTransition import androidx.compose.animation.core.Animatable -import androidx.navigation.compose.composable +import androidx.compose.animation.scaleOut import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material3.Surface +import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier import androidx.compose.ui.geometry.Offset +import androidx.compose.ui.graphics.TransformOrigin import androidx.compose.ui.input.pointer.util.VelocityTracker import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.unit.dp +import androidx.navigation.NavHostController +import androidx.navigation.compose.NavHost +import androidx.navigation.compose.composable +import androidx.navigation.compose.rememberNavController import kotlin.coroutines.cancellation.CancellationException - @Composable private fun PredictiveBackOverrideExit( modifier: Modifier, @@ -39,7 +54,7 @@ private fun PredictiveBackOverrideExit( popExitTransition = { scaleOut( targetScale = 0.9f, - transformOrigin = TransformOrigin(pivotFractionX = 0.5f, pivotFractionY = 0.5f) + transformOrigin = TransformOrigin(pivotFractionX = 0.5f, pivotFractionY = 0.5f) ) }, popEnterTransition = { @@ -66,16 +81,16 @@ private fun PredictiveBackOverrideExit( @Composable private fun HomeScreen( - modifier: Modifier = Modifier, navController: NavHostController + modifier: Modifier = Modifier, + navController: NavHostController ) { - } @Composable private fun SettingsScreen( - modifier: Modifier = Modifier, navController: NavHostController + modifier: Modifier = Modifier, + navController: NavHostController ) { - } @Composable @@ -130,7 +145,6 @@ private fun PredictiveBackHandlerManualProgress() { velocityTracker.resetTracking() } // [END android_compose_predictivebackhandler] - } } @@ -139,4 +153,4 @@ private enum class DrawerState { Closed } -private val DrawerWidth = 300.dp \ No newline at end of file +private val DrawerWidth = 300.dp From 14e2e69c419e37ba06e6421c421275c0c993037a Mon Sep 17 00:00:00 2001 From: Tram Bui Date: Fri, 15 Nov 2024 10:00:09 -0800 Subject: [PATCH 3/4] add in basic predictivebackhandler composable example --- .../predictiveback/PredictiveBackSnippets.kt | 40 ++++++++++++++++++- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/compose/snippets/src/main/java/com/example/compose/snippets/predictiveback/PredictiveBackSnippets.kt b/compose/snippets/src/main/java/com/example/compose/snippets/predictiveback/PredictiveBackSnippets.kt index 96392f88..4a620341 100644 --- a/compose/snippets/src/main/java/com/example/compose/snippets/predictiveback/PredictiveBackSnippets.kt +++ b/compose/snippets/src/main/java/com/example/compose/snippets/predictiveback/PredictiveBackSnippets.kt @@ -9,20 +9,26 @@ import androidx.compose.animation.scaleOut import androidx.compose.ui.graphics.TransformOrigin import androidx.compose.animation.EnterTransition import android.os.SystemClock +import androidx.activity.BackEventCompat import androidx.activity.compose.PredictiveBackHandler import androidx.compose.ui.unit.dp import androidx.compose.animation.core.Animatable +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box import androidx.navigation.compose.composable import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material3.Surface import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableFloatStateOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue import androidx.compose.ui.geometry.Offset +import androidx.compose.ui.graphics.Color import androidx.compose.ui.input.pointer.util.VelocityTracker import androidx.compose.ui.platform.LocalDensity +import kotlinx.coroutines.flow.Flow import kotlin.coroutines.cancellation.CancellationException @@ -78,6 +84,36 @@ private fun SettingsScreen( } +@Composable +private fun PredictiveBackHandlerBasicExample() { + + var boxScale by remember { mutableFloatStateOf(1F) } + + Box( + modifier = Modifier + .fillMaxSize(boxScale) + .background(Color.Blue) + ) + + // [START android_compose_predictivebackhandler_basic] + PredictiveBackHandler(true) {progress: Flow -> + // code for gesture back started + try { + progress.collect { backEvent -> + // code for progress + boxScale = 1F - (1F * backEvent.progress) + } + // code for completion + + } catch (e: CancellationException) { + // code for cancellation + boxScale = 1F + } + } + // [END android_compose_predictivebackhandler_basic] +} + + @Composable private fun PredictiveBackHandlerManualProgress() { @@ -112,7 +148,7 @@ private fun PredictiveBackHandlerManualProgress() { VelocityTracker() } - // [START android_compose_predictivebackhandler] + // [START android_compose_predictivebackhandler_manualprogress] PredictiveBackHandler(drawerState == DrawerState.Open) { progress -> try { progress.collect { backEvent -> @@ -129,7 +165,7 @@ private fun PredictiveBackHandlerManualProgress() { } velocityTracker.resetTracking() } - // [END android_compose_predictivebackhandler] + // [END android_compose_predictivebackhandler_manualprogress] } } From dbaf235be3c9cc3d12bdfaa18ae1af08fed6382d Mon Sep 17 00:00:00 2001 From: trambui09 Date: Fri, 15 Nov 2024 18:09:49 +0000 Subject: [PATCH 4/4] Apply Spotless --- .../snippets/predictiveback/PredictiveBackSnippets.kt | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/compose/snippets/src/main/java/com/example/compose/snippets/predictiveback/PredictiveBackSnippets.kt b/compose/snippets/src/main/java/com/example/compose/snippets/predictiveback/PredictiveBackSnippets.kt index 8431a01d..88ec5c4a 100644 --- a/compose/snippets/src/main/java/com/example/compose/snippets/predictiveback/PredictiveBackSnippets.kt +++ b/compose/snippets/src/main/java/com/example/compose/snippets/predictiveback/PredictiveBackSnippets.kt @@ -21,10 +21,9 @@ import androidx.activity.BackEventCompat import androidx.activity.compose.PredictiveBackHandler import androidx.compose.animation.EnterTransition import androidx.compose.animation.core.Animatable +import androidx.compose.animation.scaleOut import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box -import androidx.navigation.compose.composable -import androidx.compose.animation.scaleOut import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material3.Surface import androidx.compose.runtime.Composable @@ -37,9 +36,6 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.geometry.Offset import androidx.compose.ui.graphics.Color -import androidx.compose.ui.input.pointer.util.VelocityTracker -import androidx.compose.ui.platform.LocalDensity -import kotlinx.coroutines.flow.Flow import androidx.compose.ui.graphics.TransformOrigin import androidx.compose.ui.input.pointer.util.VelocityTracker import androidx.compose.ui.platform.LocalDensity @@ -49,6 +45,7 @@ import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import androidx.navigation.compose.rememberNavController import kotlin.coroutines.cancellation.CancellationException +import kotlinx.coroutines.flow.Flow @Composable private fun PredictiveBackOverrideExit( @@ -114,7 +111,7 @@ private fun PredictiveBackHandlerBasicExample() { ) // [START android_compose_predictivebackhandler_basic] - PredictiveBackHandler(true) {progress: Flow -> + PredictiveBackHandler(true) { progress: Flow -> // code for gesture back started try { progress.collect { backEvent -> @@ -122,7 +119,6 @@ private fun PredictiveBackHandlerBasicExample() { boxScale = 1F - (1F * backEvent.progress) } // code for completion - } catch (e: CancellationException) { // code for cancellation boxScale = 1F @@ -131,7 +127,6 @@ private fun PredictiveBackHandlerBasicExample() { // [END android_compose_predictivebackhandler_basic] } - @Composable private fun PredictiveBackHandlerManualProgress() {