我已经在我的项目中实现了伴奏导航动画库,并且偶然发现了两个问题。第一个问题是从一个屏幕导航到另一个屏幕时没有应用动画。第二个问题是系统的“返回”将应用程序关闭到后台而不是返回到上一个屏幕。
这是从 MainActivity 开始的应用程序布局。
MainActivity.kt
@ExperimentalAnimationApi
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
private val preDrawListener = ViewTreeObserver.OnPreDrawListener { false }
override fun onCreate(savedInstanceState: Bundle?) {
setTheme(R.style.MyHomeTheme)
super.onCreate(savedInstanceState)
WindowCompat.setDecorFitsSystemWindows(window, false)
val content: View = findViewById(android.R.id.content)
content.viewTreeObserver.addOnPreDrawListener(preDrawListener)
lifecycleScope.launch {
setContent {
val systemUiController = rememberSystemUiController()
SideEffect {
systemUiController.setStatusBarColor(
color = Color.Transparent,
darkIcons = true
)
systemUiController.setNavigationBarColor(
color = Color(0x40000000),
darkIcons = false
)
}
MyHomeApp(
currentRoute = Destinations.Welcome.WELCOME_ROUTE
)
}
unblockDrawing()
}
}
private fun unblockDrawing() {
val content: View = findViewById(android.R.id.content)
content.viewTreeObserver.removeOnPreDrawListener(preDrawListener)
content.viewTreeObserver.addOnPreDrawListener { true }
}
}
MyHomeApp.kt
@ExperimentalAnimationApi
@Composable
fun MyHomeApp(currentRoute: String) {
MyHomeTheme {
ProvideWindowInsets {
val navController = rememberAnimatedNavController()
val scaffoldState = rememberScaffoldState()
val darkTheme = isSystemInDarkTheme()
val items = listOf(
HomeTab.Dashboard,
HomeTab.Details,
HomeTab.Settings
)
val navBackStackEntry by navController.currentBackStackEntryAsState()
val currentDestination = navBackStackEntry?.destination
val bottomPaddingModifier = if (currentDestination?.route?.contains("welcome") == true) {
Modifier
} else {
Modifier.navigationBarsPadding()
}
Scaffold(
modifier = Modifier
.fillMaxSize()
.then(bottomPaddingModifier),
scaffoldState = scaffoldState,
bottomBar = {
if (currentDestination?.route in items.map { it.route }) {
BottomNavigation {
items.forEach { screen ->
BottomNavigationItem(
label = { Text(screen.title) },
icon = {},
selected = currentDestination?.hierarchy?.any { it.route == screen.route } == true,
onClick = {
navController.navigate(screen.route) {
// Pop up to the start destination of the graph to
// avoid building up a large stack of destinations
// on the back stack as users select items
popUpTo(navController.graph.findStartDestination().id) {
saveState = true
}
// Avoid multiple copies of the same destination when
// reselecting the same item
launchSingleTop = true
// Restore state when reselecting a previously selected item
restoreState = true
}
}
)
}
}
}
}
) { innerPadding ->
MyHomeNavGraph(
modifier = Modifier.padding(innerPadding),
navController = navController,
startDestination = navBackStackEntry?.destination?.route ?: currentRoute
)
}
}
}
}
sealed class HomeTab(
val route: String,
val title: String
) {
object Dashboard : HomeTab(
route = Destinations.Home.HOME_DASHBOARD,
title = "Dashboard"
)
object Details : HomeTab(
route = Destinations.Home.HOME_DETAILS,
title = "Details"
)
object Settings : HomeTab(
route = Destinations.Home.HOME_SETTINGS,
title = "Settings"
)
}
MyHomeNavGraph.kt
@ExperimentalAnimationApi
@Composable
fun MyHomeNavGraph(
modifier: Modifier = Modifier,
navController: NavHostController,
startDestination: String
) {
val actions = remember(navController) { Actions(navController = navController) }
AnimatedNavHost(
modifier = modifier,
navController = navController,
startDestination = startDestination
) {
composable(
route = Destinations.Welcome.WELCOME_ROUTE,
enterTransition = {
when (initialState.destination.route) {
Destinations.Welcome.WELCOME_LOGIN_ROUTE ->
slideIntoContainer(towards = AnimatedContentScope.SlideDirection.Left, animationSpec = tween(700))
else -> null
}
},
exitTransition = {
when (targetState.destination.route) {
Destinations.Welcome.WELCOME_LOGIN_ROUTE ->
slideOutOfContainer(towards = AnimatedContentScope.SlideDirection.Left, animationSpec = tween(700))
else -> null
}
},
popEnterTransition = {
when (initialState.destination.route) {
Destinations.Welcome.WELCOME_LOGIN_ROUTE ->
slideIntoContainer(towards = AnimatedContentScope.SlideDirection.Right, animationSpec = tween(700))
else -> null
}
},
popExitTransition = {
when (targetState.destination.route) {
Destinations.Welcome.WELCOME_LOGIN_ROUTE ->
slideOutOfContainer(towards = AnimatedContentScope.SlideDirection.Right, animationSpec = tween(700))
else -> null
}
}
) {
WelcomeScreen(
navigateToLogin = actions.navigateToWelcomeLogin,
navigateToRegister = actions.navigateToWelcomeRegister,
)
}
composable(
route = Destinations.Welcome.WELCOME_LOGIN_ROUTE,
enterTransition = {
when (initialState.destination.route) {
Destinations.Welcome.WELCOME_ROUTE ->
slideIntoContainer(towards = AnimatedContentScope.SlideDirection.Left, animationSpec = tween(700))
else -> null
}
},
exitTransition = {
when (targetState.destination.route) {
Destinations.Welcome.WELCOME_ROUTE ->
slideOutOfContainer(towards = AnimatedContentScope.SlideDirection.Left, animationSpec = tween(700))
else -> null
}
},
popEnterTransition = {
when (initialState.destination.route) {
Destinations.Welcome.WELCOME_ROUTE ->
slideIntoContainer(towards = AnimatedContentScope.SlideDirection.Right, animationSpec = tween(700))
else -> null
}
},
popExitTransition = {
when (targetState.destination.route) {
Destinations.Welcome.WELCOME_ROUTE ->
slideOutOfContainer(towards = AnimatedContentScope.SlideDirection.Right, animationSpec = tween(700))
else -> null
}
}
) {
WelcomeLoginScreen(
// Arguments will be passed to navigate to the home screen or other
)
}
}
}
class Actions(val navController: NavHostController) {
// Welcome
val navigateToWelcome = {
navController.navigate(Destinations.Welcome.WELCOME_ROUTE)
}
val navigateToWelcomeLogin = {
navController.navigate(Destinations.Welcome.WELCOME_LOGIN_ROUTE)
}
}
为简单起见,您可以假设屏幕只是一个中间有一个按钮的框,当单击它们时执行导航。
我使用的伴奏版本是 0.24.1-alpha(截至本问题的最新版本),我使用的是 compose 版本 1.2.0-alpha02 和 kotlin 1.6.10。
在动画方面,我可以看到伴奏样本的唯一区别是我没有将 navController 传递到屏幕,但我不明白这可能是一个问题。
在使用应该返回到以前的系统返回方面,我真的被什么可能导致导航关闭应用程序而不是返回。在其他项目中,系统返回工作正常,但不适用于这个。伴奏导航的使用不兼容吗?我不确定。
任何帮助表示赞赏!