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

BottomSheetFragment中onViewStateRestored触发时CardView背景不生效,选中状态丢失

问题根因

  1. 每次关闭BottomSheetFragment后,Fragment视图会走onDestroyView销毁,你存储的b:CardView?是旧视图的控件实例,下次打开新视图重建后,这个引用已经失效,自然无法生效。
  2. 状态恢复逻辑写在onViewStateRestored不适用于这个场景,且你在onViewCreated开头主动调用了RadioGroup.clearCheck(),直接清空了之前的选中状态。
  3. 仅存储View实例而非状态标识,视图重建后无法对应到新的控件。

具体修改方案

1. 调整存储变量,只存状态不存View

不要存储b、btn这类临时View实例,改为存储选中项的标识:

// 删除 private var b:CardView?=null、private var btn:Button? = null、private var cardView:CardView? = null 这三个变量
// 新增变量存储选中的卡片资源ID
private var selectedCardId: Int? = null

2. 修改Card点击监听,存储选中ID

private val listener = View.OnClickListener { v->
    val currentCard = v as CardView
    // 存储选中的卡片资源ID,而非View实例
    selectedCardId = currentCard.id
    currentCard.setCardBackgroundColor(Color.BLACK)
    val linearLayout = currentCard.getChildAt(0) as LinearLayout
    val constrainLinearLayout = linearLayout.getChildAt(0) as ConstraintLayout
    val textView = constrainLinearLayout.getChildAt(0) as TextView
    textView.setTextColor(Color.WHITE)
    previousSelectRating = textView.text.toString()
    reset(currentCard.resources.getResourceEntryName(currentCard.id))
}

3. 把状态恢复逻辑移到onViewCreated末尾,替换无用的onViewStateRestored

删除你现在的onViewStateRestored方法所有代码,在onViewCreated的最后(dismiss点击事件后面)加恢复逻辑:

// 恢复CardView选中状态
selectedCardId?.let { cardId ->
    val selectedCard = view.findViewById<CardView>(cardId) ?: return@let
    selectedCard.setCardBackgroundColor(Color.BLACK)
    val linearLayout = selectedCard.getChildAt(0) as LinearLayout
    val constrainLinearLayout = linearLayout.getChildAt(0) as ConstraintLayout
    val textView = constrainLinearLayout.getChildAt(0) as TextView
    textView.setTextColor(Color.WHITE)
    reset(selectedCard.resources.getResourceEntryName(selectedCard.id))
}

// 恢复RadioGroup选中状态,注意先临时移除监听器避免冲突
previousSelect?.let { selectId ->
    if (selectId != -1) {
        radioGroup1.setOnCheckedChangeListener(null)
        radioGroup2.setOnCheckedChangeListener(null)
        if (findViewById<RadioButton>(selectId)?.parent == radioGroup1) {
            radioGroup1.check(selectId)
            radioGroup2.clearCheck()
        } else {
            radioGroup2.check(selectId)
            radioGroup1.clearCheck()
        }
        radioGroup1.setOnCheckedChangeListener(listener1)
        radioGroup2.setOnCheckedChangeListener(listener2)
        changeTextColor(selectId, "White")
    }
}

previousSelectPrice?.let { priceId ->
    if (priceId != -1) {
        radioGroup3.setOnCheckedChangeListener(null)
        radioGroup3.check(priceId)
        radioGroup3.setOnCheckedChangeListener(listener3)
        changeTextColor(priceId, "White")
    }
}

4. 调整开头的RadioGroup清空逻辑

把onViewCreated开头的radioGroup1.clearCheck()、radioGroup2.clearCheck()改为只有首次打开没有选中状态时才清空:

if (previousSelect == null) {
    radioGroup1.clearCheck()
    radioGroup2.clearCheck()
}
if (previousSelectPrice == null) {
    radioGroup3.clearCheck()
}

补充说明

如果你每次打开底部弹窗都是新建Fragment实例,那成员变量会被重置,需要在新建实例时把之前的选中状态通过arguments传入,或者将选中状态存在宿主Activity/共享ViewModel中即可。

内容的提问来源于stack exchange,提问作者Souhil Hadj Habib

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.23 21:54:03