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

Android Jetpack Compose:如何让ItemSkillView获取StatsField输入数据

解决方案

1. 修复StatsField的状态更新逻辑

你当前代码里所有StatsField的onValueChange都调用skillViewModel.updateStrenghtValue(it),这会导致只有力量值被更新,敏捷、体质等其他属性从未被正确赋值。需要为每个属性绑定对应的ViewModel更新方法:

修改CharacterSkillScreen中的循环逻辑:

statsField.forEach { (label, value) ->
    StatsField(
        label = label,
        value = value.toString(),
        onValueChange = { newValue ->
            when(label) {
                "FOR" -> skillViewModel.updateStrenghtValue(newValue)
                "DEX" -> skillViewModel.updateDexterityValue(newValue)
                "CON" -> skillViewModel.updateConstitutionValue(newValue)
                "INT" -> skillViewModel.updateIntelligenceValue(newValue)
                "SAG" -> skillViewModel.updateWisdomValue(newValue)
                "CHA" -> skillViewModel.updateCharismValue(newValue)
            }
        },
        modifier = Modifier.weight(1f)
    )
}

2. 完善SkillViewModel的状态管理

确保SkillViewModel包含所有属性的状态,并提供初始化方法,用来接收导航传递的初始值:

class SkillViewModel : ViewModel() {
    private val _uiState = MutableStateFlow(SkillUiState())
    val uiState = _uiState.asStateFlow()

    // 用导航参数初始化状态
    fun initializeStats(
        strength: String,
        dexterity: String,
        constitution: String,
        intelligence: String,
        wisdom: String,
        charism: String
    ) {
        _uiState.update {
            it.copy(
                strenght = strength,
                dexterity = dexterity,
                constitution = constitution,
                intelligence = intelligence,
                wisdom = wisdom,
                charism = charism
            )
        }
    }

    // 各属性的单独更新方法
    fun updateStrenghtValue(value: String) {
        _uiState.update { it.copy(strenght = value) }
    }

    fun updateDexterityValue(value: String) {
        _uiState.update { it.copy(dexterity = value) }
    }

    fun updateConstitutionValue(value: String) {
        _uiState.update { it.copy(constitution = value) }
    }

    fun updateIntelligenceValue(value: String) {
        _uiState.update { it.copy(intelligence = value) }
    }

    fun updateWisdomValue(value: String) {
        _uiState.update { it.copy(wisdom = value) }
    }

    fun updateCharismValue(value: String) {
        _uiState.update { it.copy(charism = value) }
    }

    // 保留原有updateSkillTitle等方法
    fun updateSkillTitle(title: String) {
        _uiState.update { it.copy(skillTitle = title) }
    }
}

data class SkillUiState(
    val strenght: String = "",
    val dexterity: String = "",
    val constitution: String = "",
    val intelligence: String = "",
    val wisdom: String = "",
    val charism: String = "",
    val skillTitle: String = ""
)

3. 在CharacterSkillScreen中初始化ViewModel状态

添加LaunchedEffect,页面加载时用导航参数初始化SkillViewModel的初始值:

@Composable
fun CharacterSkillScreen(
    strenghtValue: String? = "",
    dexterityValue: String? = "",
    constitutionValue: String? = "",
    intelligenceValue: String? = "",
    wisdomValue: String? = "",
    charismValue: String? = "",
    skillViewModel: SkillViewModel = viewModel()
) {
    val addedSkill = remember { mutableStateListOf<@Composable () -> Unit>() }
    val skillUiState by skillViewModel.uiState.collectAsState()

    // 初始化状态
    LaunchedEffect(Unit) {
        skillViewModel.initializeStats(
            strenghtValue.orEmpty(),
            dexterityValue.orEmpty(),
            constitutionValue.orEmpty(),
            intelligenceValue.orEmpty(),
            wisdomValue.orEmpty(),
            charismValue.orEmpty()
        )
    }

    // 保留原有Column、LazyColumn等代码...
}

4. 在ItemSkillView中直接获取状态值

现在可以在ItemSkillView中直接从skillViewModel.uiState读取所有属性值,比如使用敏捷值:

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun ItemSkillView(
    skillViewModel: SkillViewModel = viewModel(),
    resultActionPoints: String = "0"
) {
    val uiState by skillViewModel.uiState.collectAsState()
    var isExpanded by remember { mutableStateOf(false) }

    Column(
        modifier = Modifier
            .fillMaxWidth()
            .clickable { isExpanded = !isExpanded }
            .animateContentSize()
    ) {
        // 示例:显示当前敏捷值
        Text(text = "当前敏捷值:${uiState.dexterity}")

        // 保留原有ConstraintLayout、TextField等代码...
    }
}

问题根源说明

  • 之前所有StatsField都只更新力量值,导致其他属性从未被写入ViewModel,自然无法获取
  • 未用导航参数初始化SkillViewModel的初始状态,进入页面时属性为空
  • 使用CharacterViewModel时可能因为作用域不匹配(属于不同导航图),无法共享状态,而SkillViewModel是当前页面专属ViewModel,作用域匹配可正确共享状态

内容的提问来源于stack exchange,提问作者Olhm.exe

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 20:24:52