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

Compose应用跨可组合项导航失效,多屏适配遇问题

解决方案实现步骤

1. 核心状态管理:用ViewModel统一控制全局状态

创建ViewModel持有选中的分类、推荐项及筛选逻辑,确保不同屏幕模式下状态同步:

class MyCityViewModel : ViewModel() {
    // 假设你已有Category和Recommendation数据类
    private val allCategories = getCategories() // 你的分类数据源
    private val allRecommendations = getRecommendations() // 你的推荐数据源

    // 默认选中第一个分类
    private val _selectedCategory = mutableStateOf(allCategories.first())
    val selectedCategory: State<Category> = _selectedCategory

    // 根据选中分类自动筛选推荐列表
    val filteredRecommendations: State<List<Recommendation>> = derivedStateOf {
        allRecommendations.filter { it.categoryId == selectedCategory.value.id }
    }

    // 默认选中筛选列表的第一个推荐项
    private val _selectedRecommendation = mutableStateOf(filteredRecommendations.value.firstOrNull())
    val selectedRecommendation: State<Recommendation?> = _selectedRecommendation

    // 切换分类时自动选中首个推荐
    fun onCategorySelected(category: Category) {
        _selectedCategory.value = category
        _selectedRecommendation.value = filteredRecommendations.value.firstOrNull()
    }

    // 切换选中的推荐项
    fun onRecommendationSelected(recommendation: Recommendation) {
        _selectedRecommendation.value = recommendation
    }
}

2. 适配Compact模式:栈式导航实现页面跳转

集成Navigation Compose规范页面跳转,不会破坏多屏适配:

导航路由定义

sealed class Screen(val route: String) {
    object Categories : Screen("categories")
    object Recommendations : Screen("recommendations/{categoryId}") {
        fun createRoute(categoryId: String) = "recommendations/$categoryId"
    }
    object Detail : Screen("detail/{recommendationId}") {
        fun createRoute(recommendationId: String) = "detail/$recommendationId"
    }
}

导航宿主与页面实现

@Composable
fun MyCityNavHost(viewModel: MyCityViewModel = viewModel()) {
    val navController = rememberNavController()
    NavHost(navController = navController, startDestination = Screen.Categories.route) {
        composable(Screen.Categories.route) {
            CategoriesScreen(
                categories = viewModel.allCategories,
                onCategoryClick = { category ->
                    navController.navigate(Screen.Recommendations.createRoute(category.id))
                }
            )
        }
        composable(Screen.Recommendations.route) { backStackEntry ->
            val categoryId = backStackEntry.arguments?.getString("categoryId") ?: ""
            val recommendations = viewModel.allRecommendations.filter { it.categoryId == categoryId }
            
            RecommendationsScreen(
                recommendations = recommendations,
                onRecommendationClick = { recommendation ->
                    navController.navigate(Screen.Detail.createRoute(recommendation.id))
                },
                onBackClick = { navController.popBackStack() }
            )
        }
        composable(Screen.Detail.route) { backStackEntry ->
            val recommendationId = backStackEntry.arguments?.getString("recommendationId") ?: ""
            val recommendation = viewModel.allRecommendations.find { it.id == recommendationId }
            
            recommendation?.let {
                DetailScreen(
                    recommendation = it,
                    onBackClick = { navController.popBackStack() }
                )
            }
        }
    }
}

3. 适配Expanded模式:横向分栏布局

通过WindowSizeClass判断屏幕类型,Expanded模式下采用三栏布局同步ViewModel状态:

@Composable
fun MyCityApp() {
    val viewModel: MyCityViewModel = viewModel()
    val windowSizeClass = calculateWindowSizeClass(LocalContext.current)
    
    when (windowSizeClass.widthSizeClass) {
        WindowWidthSizeClass.Expanded -> {
            Row(modifier = Modifier.fillMaxSize()) {
                // 左侧分类栏
                CategoriesScreen(
                    categories = viewModel.allCategories,
                    selectedCategory = viewModel.selectedCategory.value,
                    onCategoryClick = viewModel::onCategorySelected,
                    modifier = Modifier.weight(1f)
                )
                // 中间推荐列表栏
                RecommendationsScreen(
                    recommendations = viewModel.filteredRecommendations.value,
                    selectedRecommendation = viewModel.selectedRecommendation.value,
                    onRecommendationClick = viewModel::onRecommendationSelected,
                    modifier = Modifier.weight(2f)
                )
                // 右侧详情栏
                viewModel.selectedRecommendation.value?.let {
                    DetailScreen(
                        recommendation = it,
                        modifier = Modifier.weight(3f)
                    )
                } ?: EmptyDetailScreen(modifier = Modifier.weight(3f))
            }
        }
        else -> {
            // Compact模式使用导航宿主
            MyCityNavHost(viewModel)
        }
    }
}

4. 关键细节处理

  • 默认展示首个推荐:在onCategorySelected方法中,切换分类后自动将选中推荐设为筛选列表的首个条目,保证Expanded模式下详情栏自动更新。
  • 筛选逻辑自动化:通过derivedStateOf监听分类变化,自动更新推荐列表,无需手动维护筛选结果。
  • 状态全局同步:所有交互操作都通过ViewModel修改状态,确保两种模式下状态一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 08:13:24