如何向屏幕添加滑动行为?
How to add swipe behavior to the screens?
我们的应用程序中有底部导航,我们想在我们的屏幕中添加滑动行为,这样如果用户滑动到 right/left,那么 s/he 应该导航到下一个屏幕。
我知道 Accompanist 有 HorizontalPager
带标签。但我想知道我们是否可以通过底部导航实现这种行为。
如您在 Material Design Guidelines 中所见:
Using swipe gestures on the content area does not navigate between views.
还有:
Avoid using lateral motion to transition between views.
但是,如果你真的想这样做,你可以这样做:
fun BottomNavSwipeScreen() {
// This scope is necessary to change the tab using animation
val scope = rememberCoroutineScope()
// I'm using a list of images here
val images = listOf(R.drawable.img1, ...)
// This page state will be used by BottomAppbar and HorizontalPager
val pageState = rememberPagerState(pageCount = images.size)
val scaffoldState = rememberScaffoldState()
Scaffold(
scaffoldState = scaffoldState,
bottomBar = {
BottomAppBar(
backgroundColor = MaterialTheme.colors.primary,
content = {
for (page in images.indices) {
BottomNavigationItem(
icon = {
Icon(Icons.Filled.Home, "Page $page")
},
// here's the trick. the selected tab is based
// on HorizontalPager state.
selected = page == pageState.currentPage,
onClick = {
// When a tab is selected,
// the page is updated
scope.launch {
pageState.animateScrollToPage(page)
}
},
selectedContentColor = Color.Magenta,
unselectedContentColor = Color.LightGray,
label = { Text(text = "Page $page") }
)
}
}
)
},
) {
HorizontalPager(
state = pageState,
offscreenLimit = 2
) { page ->
Image(
painterResource(id = images[page]),
null,
modifier = Modifier
.fillMaxSize(),
contentScale = ContentScale.Crop
)
}
}
}
结果如下:
您可以使用 compose 中的动画库实现此目的:
https://developer.android.com/jetpack/compose/animation
并且使用slideIntoContainer
动画可以模拟滑动效果:
composable("route1",
enterTransition = {
slideIntoContainer(
towards = AnimatedContentScope.SlideDirection.Right,
animationSpec = tween(
durationMillis = 250,
easing = LinearEasing // interpolator
)
)
},
exitTransition = {
slideOutOfContainer(
towards = AnimatedContentScope.SlideDirection.Left,
animationSpec = tween(
durationMillis = 250,
easing = LinearEasing
)
)
}) {
Screen1()
}
composable("route2",
enterTransition = {
slideIntoContainer(
towards = AnimatedContentScope.SlideDirection.Left,
animationSpec = tween(
durationMillis = 250,
easing = LinearEasing // interpolator
)
)
},
exitTransition = {
slideOutOfContainer(
towards = AnimatedContentScope.SlideDirection.Right,
animationSpec = tween(
durationMillis = 250,
easing = LinearEasing
)
)
}) {
Screen2()
}
我们的应用程序中有底部导航,我们想在我们的屏幕中添加滑动行为,这样如果用户滑动到 right/left,那么 s/he 应该导航到下一个屏幕。
我知道 Accompanist 有 HorizontalPager
带标签。但我想知道我们是否可以通过底部导航实现这种行为。
如您在 Material Design Guidelines 中所见:
Using swipe gestures on the content area does not navigate between views.
还有:
Avoid using lateral motion to transition between views.
但是,如果你真的想这样做,你可以这样做:
fun BottomNavSwipeScreen() {
// This scope is necessary to change the tab using animation
val scope = rememberCoroutineScope()
// I'm using a list of images here
val images = listOf(R.drawable.img1, ...)
// This page state will be used by BottomAppbar and HorizontalPager
val pageState = rememberPagerState(pageCount = images.size)
val scaffoldState = rememberScaffoldState()
Scaffold(
scaffoldState = scaffoldState,
bottomBar = {
BottomAppBar(
backgroundColor = MaterialTheme.colors.primary,
content = {
for (page in images.indices) {
BottomNavigationItem(
icon = {
Icon(Icons.Filled.Home, "Page $page")
},
// here's the trick. the selected tab is based
// on HorizontalPager state.
selected = page == pageState.currentPage,
onClick = {
// When a tab is selected,
// the page is updated
scope.launch {
pageState.animateScrollToPage(page)
}
},
selectedContentColor = Color.Magenta,
unselectedContentColor = Color.LightGray,
label = { Text(text = "Page $page") }
)
}
}
)
},
) {
HorizontalPager(
state = pageState,
offscreenLimit = 2
) { page ->
Image(
painterResource(id = images[page]),
null,
modifier = Modifier
.fillMaxSize(),
contentScale = ContentScale.Crop
)
}
}
}
结果如下:
您可以使用 compose 中的动画库实现此目的: https://developer.android.com/jetpack/compose/animation
并且使用slideIntoContainer
动画可以模拟滑动效果:
composable("route1",
enterTransition = {
slideIntoContainer(
towards = AnimatedContentScope.SlideDirection.Right,
animationSpec = tween(
durationMillis = 250,
easing = LinearEasing // interpolator
)
)
},
exitTransition = {
slideOutOfContainer(
towards = AnimatedContentScope.SlideDirection.Left,
animationSpec = tween(
durationMillis = 250,
easing = LinearEasing
)
)
}) {
Screen1()
}
composable("route2",
enterTransition = {
slideIntoContainer(
towards = AnimatedContentScope.SlideDirection.Left,
animationSpec = tween(
durationMillis = 250,
easing = LinearEasing // interpolator
)
)
},
exitTransition = {
slideOutOfContainer(
towards = AnimatedContentScope.SlideDirection.Right,
animationSpec = tween(
durationMillis = 250,
easing = LinearEasing
)
)
}) {
Screen2()
}