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 ->
    // 显示对应页面
}
相关推荐
jyan_敬言16 分钟前
【C++】string类(二)相关接口介绍及其使用
android·开发语言·c++·青少年编程·visual studio
程序员老刘36 分钟前
Android 16开发者全解读
android·flutter·客户端
福柯柯2 小时前
Android ContentProvider的使用
android·contenprovider
不想迷路的小男孩2 小时前
Android Studio 中Palette跟Component Tree面板消失怎么恢复正常
android·ide·android studio
餐桌上的王子2 小时前
Android 构建可管理生命周期的应用(一)
android
菠萝加点糖2 小时前
Android Camera2 + OpenGL离屏渲染示例
android·opengl·camera
用户2018792831672 小时前
🌟 童话:四大Context徽章诞生记
android
yzpyzp2 小时前
Android studio在点击运行按钮时执行过程中输出的compileDebugKotlin 这个任务是由gradle执行的吗
android·gradle·android studio
aningxiaoxixi2 小时前
安卓之service
android
TeleostNaCl3 小时前
Android 应用开发 | 一种限制拷贝速率解决因 IO 过高导致系统卡顿的方法
android·经验分享