Compose仿微信底部导航栏NavigationBar :底部导航控制滑动并移动

文章目录

  • 1、准备工作
  • 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 实现在一个应用程序的主要目的地之间移动

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 ->
    // 显示对应页面
}
相关推荐
alexhilton4 小时前
灵活、现代的Android应用架构:完整分步指南
android·kotlin·android jetpack
hnlgzb6 小时前
build.gradle中的dependencies 中API
android
xiaguangbo7 小时前
rust slint android 安卓
android·linux·rust
lichong9517 小时前
【大前端++】Android studio Log日志高对比度配色方案
android·java·前端·json·android studio·大前端·大前端++
00后程序员张9 小时前
iOS 开发环境搭建完整指南 Xcode 安装配置、iOS 开发工具选择、ipa 打包与 App Store 上架实战经验
android·macos·ios·小程序·uni-app·iphone·xcode
顾林海9 小时前
揭秘Android编译插桩:ASM让你的代码"偷偷"变强
android·面试·性能优化
雨白10 小时前
初识协程: 为什么需要它以及如何启动第一个协程
android·kotlin
文阿花10 小时前
flutter 3.22+ Android集成高德Flutter地图自定义Marker显示
android·flutter
豆豆豆大王11 小时前
Android studio图像视图和相对布局知识点
android·ide·android studio
我命由我1234512 小时前
Android 实例 - Android 圆形蒙版(Android 圆形蒙版实现、圆形蒙版解读)
android·java·java-ee·android studio·安卓·android-studio·android runtime