accompanist: [Navigation] sheet destination not popped when rapidly dismissing sheet
Description
I have a layout where a FAB triggers the bottom sheet, and then disappears so as not to cover it. When the sheet is dismissed, the button reappears (see the video under ‘expected behaviour’).
This works most of the time, however if the sheet is dismissed at a particular moment shortly after it’s started, it seems that the the currentBackStackEntryAsState state isn’t updated back to the prior destination, and therefore the action to show the button isn’t run. There appears to be a race condition.
Video of the failing case:
https://user-images.githubusercontent.com/1038350/154358665-7326cd6e-6a35-485c-b0c3-65fbf9313a2b.mp4
Steps to reproduce
- Press the button to switch to the sheet and hide the button.
- Press the scrim, just about at the time when the sheet animation stops.
- Observe that sheet is dismissed, but the button has not reappeared.
Also, in terms of a bit of troubleshooting…
- If I add a
printlnas follows:
within myval navBackStackEntry by navController.currentBackStackEntryAsState() // existing line println("Route: ${navBackStackEntry?.destination?.route}") // new printlnMainLayout, then in the erroneous case it ends onSHEET. TheHOMEnavigation does not appear to be triggered.
Full code below.
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Star
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.graphics.vector.rememberVectorPainter
import androidx.compose.ui.unit.sp
import androidx.navigation.NavHostController
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.compose.rememberNavController
import com.google.accompanist.navigation.material.*
class TestActivity2 : ComponentActivity() {
@OptIn(ExperimentalMaterialNavigationApi::class, ExperimentalMaterial3Api::class)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
val bottomSheetNavigator = rememberBottomSheetNavigator()
val navController = rememberNavController(bottomSheetNavigator)
var fabVisible by remember { mutableStateOf(true) }
Scaffold(
floatingActionButton = {
if (fabVisible) {
FloatingActionButton(onClick = {
navController.navigate(Destinations.SHEET.name)
}) {
Icon(
painter = rememberVectorPainter(image = Icons.Default.Star),
contentDescription = null
)
}
}
},
) {
MainLayout(
bottomSheetNavigator = bottomSheetNavigator,
navController = navController,
onShowSheet = { fabVisible = false },
onHideSheet = { fabVisible = true },
)
}
}
}
@OptIn(ExperimentalMaterialNavigationApi::class)
@Composable
fun MainLayout(
bottomSheetNavigator: BottomSheetNavigator,
navController: NavHostController,
onShowSheet: () -> Unit = {},
onHideSheet: () -> Unit = {}
) {
val navBackStackEntry by navController.currentBackStackEntryAsState()
if (navBackStackEntry?.destination?.route == Destinations.SHEET.name) {
onShowSheet()
} else {
onHideSheet()
}
ModalBottomSheetLayout(bottomSheetNavigator) {
NavHost(navController, Destinations.HOME.name) {
composable(route = Destinations.HOME.name) {
Text("This is the home.", fontSize = 16.sp)
}
bottomSheet(route = Destinations.SHEET.name) {
Text("This is the bottom sheet.", fontSize = 16.sp)
}
}
}
}
private enum class Destinations {
HOME, SHEET
}
}
Expected behavior
The logic to re-enable the button is triggered, regardless of how quickly I dismiss the sheet.
https://user-images.githubusercontent.com/1038350/154358541-1af846e4-96d0-4d17-9bff-bbab977ae450.mp4
Additional context
Compose version 1.2.0-alpha03 Accompanist version 0.24.2-alpha Android S (Pixel 3a) and Android S (Nexus 5 emulator)
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Comments: 26
@jossiwolf please could you reopen this? It appears to have been closed in error.
Is this really closed as completed? I don’t see any related changes. I feel like the bot just ignored someone commenting.
Hi @ind1go, thank you! Yes, Swipeable and ModalBottomSheetLayout which we use have a 1-frame delay, resulting in a race condition. We are doing some work upstream but this is dependent on a bigger redesign of the underlying APIs. For now, we can’t offer a good solution for this issue, but I will provide any updates when I can.