You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在NavHost Controller中结合使用Jetpack HorizontalPager与HorizontalPagerIndicator

在NavHost Controller中结合Jetpack HorizontalPager与HorizontalPagerIndicator实现9页面导航

1. 依赖配置

首先确保项目引入必要依赖:

dependencies {
    // Compose Navigation
    implementation("androidx.navigation:navigation-compose:2.7.6")
    // Jetpack Pager & Material3 Indicator
    implementation("androidx.compose.foundation:foundation:1.5.4")
    implementation("androidx.compose.material3:material3:1.1.2")
}

2. 定义页面路由与映射逻辑

统一管理9个页面的路由,建立路由与索引的双向映射:

// 9个页面的路由列表
private val pageRoutes = listOf(
    "page_1", "page_2", "page_3",
    "page_4", "page_5", "page_6",
    "page_7", "page_8", "page_9"
)

// 根据路由获取对应页面索引
private fun getPageIndex(route: String): Int = pageRoutes.indexOf(route).coerceAtLeast(0)

// 根据索引获取对应页面路由
private fun getPageRoute(index: Int): String = pageRoutes.getOrElse(index) { pageRoutes.first() }

3. 创建ViewModel管理导航与Pager状态

用ViewModel同步NavHost导航状态和HorizontalPager的页面索引:

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewmodelScope
import androidx.navigation.NavHostController
import kotlinx.coroutines.launch
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.setValue

class PagerNavViewModel : ViewModel() {
    var currentPageIndex by mutableStateOf(0)
        private set

    // 监听NavHost导航变化,同步到Pager索引
    fun syncNavToPager(navController: NavHostController) {
        viewModelScope.launch {
            navController.currentBackStackEntryFlow.collect { entry ->
                entry?.destination?.route?.let { route ->
                    currentPageIndex = getPageIndex(route)
                }
            }
        }
    }

    // 当Pager切换页面时,同步到NavHost导航
    fun syncPagerToNav(navController: NavHostController, newIndex: Int) {
        if (newIndex != currentPageIndex) {
            currentPageIndex = newIndex
            val targetRoute = getPageRoute(newIndex)
            if (navController.currentDestination?.route != targetRoute) {
                navController.navigate(targetRoute) {
                    // 避免重复入栈,保持单实例
                    popUpTo(navController.graph.startDestinationId) { inclusive = false }
                    launchSingleTop = true
                }
            }
        }
    }
}

4. 主Composable实现联动逻辑

整合HorizontalPager、HorizontalPagerIndicator和NavHost,实现双向同步:

import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Scaffold
import androidx.compose.material3.HorizontalPager
import androidx.compose.material3.HorizontalPagerIndicator
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import androidx.compose.foundation.pager.rememberPagerState

@Composable
fun PagerNavHostScreen() {
    val viewModel: PagerNavViewModel = viewModel()
    val navController = rememberNavController()
    // 初始化Pager状态,页面数量为9
    val pagerState = rememberPagerState(pageCount = pageRoutes.size)

    // 初始化:同步NavHost初始路由到Pager
    LaunchedEffect(Unit) {
        viewModel.syncNavToPager(navController)
    }

    // Pager页面切换时,同步到NavHost导航
    LaunchedEffect(pagerState.currentPage) {
        viewModel.syncPagerToNav(navController, pagerState.currentPage)
    }

    // ViewModel索引变化时,同步到Pager滚动
    LaunchedEffect(viewModel.currentPageIndex) {
        pagerState.animateScrollToPage(viewModel.currentPageIndex)
    }

    Scaffold(
        bottomBar = {
            // 底部显示页面指示器
            HorizontalPagerIndicator(
                pagerState = pagerState,
                modifier = Modifier
                    .fillMaxSize()
                    .padding(16.dp),
                activeColor = MaterialTheme.colorScheme.primary,
                inactiveColor = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.3f)
            )
        }
    ) { paddingValues ->
        Surface(
            modifier = Modifier
                .fillMaxSize()
                .padding(paddingValues)
        ) {
            HorizontalPager(
                state = pagerState,
                modifier = Modifier.fillMaxSize()
            ) { pageIndex ->
                // 每个Pager页面对应NavHost的一个目的地
                NavHost(
                    navController = navController,
                    startDestination = pageRoutes.first()
                ) {
                    pageRoutes.forEachIndexed { index, route ->
                        composable(route) {
                            // 替换为你的实际页面内容
                            PageContent(pageNumber = index + 1)
                        }
                    }
                }
            }
        }
    }
}

// 示例页面组件,替换成你的业务页面
@Composable
fun PageContent(pageNumber: Int) {
    // 这里编写页面UI逻辑
}

关键注意事项

  • 回退栈控制:若需支持返回键,可在syncPagerToNav的navigate方法中调整popUpTo参数,或监听返回键事件同步更新Pager索引。
  • 状态保存:每个页面的状态请用rememberSaveable或专属ViewModel管理,避免页面切换时状态丢失。
  • 性能优化:通过HorizontalPager的beyondBoundsPageCount参数控制预加载页面数量,减少不必要的资源消耗。

内容的提问来源于stack exchange,提问作者Slava

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 11:14:51