文章目录
- 1、准备工作
-
- [1.1 参考](#1.1 参考)
- [1.2 依赖添加:](#1.2 依赖添加:)
- [1.3 主要控件](#1.3 主要控件)
- 2、功能描述:
- 3、实现过程
-
- [3.1 创建一个数据类](#3.1 创建一个数据类)
- [3.2 创建一个list变量](#3.2 创建一个list变量)
- [3.3 具体实现](#3.3 具体实现)
-
- [3.3.1 创建共享的Pager状态](#3.3.1 创建共享的Pager状态)
- [3.3.2 将页面索引与页面标题同步](#3.3.2 将页面索引与页面标题同步)
- [3.3.3 创建协程作用域](#3.3.3 创建协程作用域)
- [3.3.4 使用HorizontalPager实现滑动效果](#3.3.4 使用HorizontalPager实现滑动效果)
- 代码实现注意点
- 4、关键点
-
- [4.1 状态管理重构:](#4.1 状态管理重构:)
- [4.2 滑动与导航同步](#4.2 滑动与导航同步)
1、准备工作
1.1 参考
组件BottomNavigation实现,版本变更后,Material 3 引入了 NavigationBar 作为 BottomNavigation 的替代品,提供更符合现代设计规范的外观和功能,使用使用 NavigationBar + NavigationBarItem进行实现。
1.2 依赖添加:
使用Bom的版本为2024.04.01,详细介绍见官网
1.3 主要控件
NavigationBar
NavigationBar 实现在一个应用程序的主要目的地之间移动
kotlin
@Composable
fun NavigationBar(
modifier: Modifier = Modifier,
containerColor: Color = NavigationBarDefaults.containerColor,
contentColor: Color = MaterialTheme.colorScheme.contentColorFor(containerColor),
tonalElevation: Dp = NavigationBarDefaults.Elevation,
windowInsets: WindowInsets = NavigationBarDefaults.windowInsets,
content: @Composable RowScope.() -> Unit
)
HorizontalPager、VerticalPager
HorizontalPager控制控件左右移动,VerticalPager控制控件上下移动
kotlin
@Composable
fun HorizontalPager(
state: PagerState,
modifier: Modifier = Modifier,
contentPadding: PaddingValues = PaddingValues(0.dp),
pageSize: PageSize = PageSize.Fill,
beyondViewportPageCount: Int = PagerDefaults.BeyondViewportPageCount,
pageSpacing: Dp = 0.dp,
verticalAlignment: Alignment.Vertical = Alignment.CenterVertically,
flingBehavior: TargetedFlingBehavior = PagerDefaults.flingBehavior(state = state),
userScrollEnabled: Boolean = true,
reverseLayout: Boolean = false,
key: ((index: Int) -> Any)? = null,
pageNestedScrollConnection: NestedScrollConnection = PagerDefaults.pageNestedScrollConnection(
state,
Orientation.Horizontal
),
snapPosition: SnapPosition = SnapPosition.Start,
pageContent: @Composable PagerScope.(page: Int) -> Unit
2、功能描述:
在底部导航栏中设置按钮,点击按钮切换页面,或者将页面左右滑动
如图所示:

3、实现过程
3.1 创建一个数据类
kotlin
data class FileBean(
val icon:Int = -1,
val title:String = "",
)
3.2 创建一个list变量
bottomNavigationList 变量声明需要的icon和title内容
kotlin
val bottomNavigationList =
mutableListOf(
FileBean(
icon = R.mipmap.icon_home_page,
title = stringResource(R.string.home_text)
),
FileBean(
icon = R.mipmap.icon_case_page,
title = stringResource(R.string.case_text)
),
FileBean(
icon = R.mipmap.icon_evidence_page,
title = stringResource(R.string.evidence_text)
),
FileBean(
icon = R.mipmap.icon_request_page,
title = stringResource(R.string.request_text)
),
FileBean(
icon = R.mipmap.icon_my_page,
title = stringResource(R.string.my_text)
),
)
3.3 具体实现
3.3.1 创建共享的Pager状态
kotlin
val pagerState = rememberPagerState(pageCount = { bottomNavigationList.size })
3.3.2 将页面索引与页面标题同步
kotlin
val currentPageTitle by remember {
derivedStateOf {
bottomNavigationList[pagerState.currentPage].title
}
}
3.3.3 创建协程作用域
kotlin
val coroutineScope = rememberCoroutineScope()
3.3.4 使用HorizontalPager实现滑动效果
kotlin
val pagerState = rememberPagerState(pageCount = { bottomNavigationList.size })
val currentPageTitle by remember {
derivedStateOf {
bottomNavigationList[pagerState.currentPage].title
}
}
val coroutineScope = rememberCoroutineScope()
Scaffold(
bottomBar = {
NavigationBar(containerColor = Color.White) {
bottomNavigationList.forEachIndexed { index, item ->
NavigationBarItem(
icon = {
Icon(
painter = painterResource(id = item.icon),
contentDescription = item.title
)
},
label = { Text(item.title) },
selected = currentPageTitle == item.title,
onClick = {
// 点击导航项时平滑滚动到对应页面
coroutineScope.launch {
pagerState.animateScrollToPage(index)
}
},
colors = NavigationBarItemDefaults.colors(
indicatorColor = Color.Transparent,
selectedIconColor = colorResource(R.color.agree_red),
selectedTextColor = colorResource(R.color.agree_red),
unselectedIconColor = colorResource(R.color.agree_grey),
unselectedTextColor = colorResource(R.color.agree_grey),
)
)
}
}
}
) { paddingValues ->
//使用HorizontalPager实现滑动效果
HorizontalPager(
state = pagerState,
modifier = Modifier.padding(paddingValues),
verticalAlignment = Alignment.Top,
beyondViewportPageCount = 0 //正常会预加载下一页,但是页面复杂会导致性能下降,将其设置为0
) { pageIndex ->
// 根据当前页面索引显示对应内容
when (pageIndex) {
0 -> HomePage()
1 -> FilePage()
2 -> VideoPage()
3 -> RequestPage()
4 -> MyPage()
}
}
}
代码实现注意点
beyondViewportPageCount 字段
需要注意的是,使用HorizontalPager时会自动加载下一页,如果每一页面较为复杂的话,会影响性能,可以通过beyondViewportPageCount 字段控制页面的加载效果,但是会影响滑动的流畅度,可以选择进行设置。
4、关键点
4.1 状态管理重构:
使用 rememberPagerState 统一管理页面状态
通过 derivedStateOf 自动同步页面索引和标题
4.2 滑动与导航同步
kotlin
// 点击导航项时滚动到对应页面
onClick = {
coroutineScope.launch {
pagerState.animateScrollToPage(index)
}
}
// HorizontalPager自动更新当前页面索引
HorizontalPager(state = pagerState) { pageIndex ->
// 显示对应页面
}