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

Flutter中基于Container和SetState的选择框在BottomSheet选中无响应求助

问题原因

问题出在showModalBottomSheet的特性上——它会创建一个独立于主页面的Widget树。虽然你的代码都在同一个State类里,但调用主页面的setState()只会刷新主页面的UI,BottomSheet的Widget树不会跟着重新构建。所以你点击按钮时_selectedVariant确实更新了,但BottomSheet里的按钮状态不会同步变化。

解决方案

方案1:用StatefulBuilder实现局部刷新

给BottomSheet内容包裹StatefulBuilder,获取能刷新BottomSheet自身的setState方法,替代主页面的setState:

修改BottomSheet调用代码

onPressed: (){
  showModalBottomSheet(
    context: context,
    builder: (BuildContext context) {
      // 用StatefulBuilder提供BottomSheet专属的刷新方法
      return StatefulBuilder(
        builder: (context, bottomSheetSetState) {
          return bottomContainer(context, bottomSheetSetState);
        },
      );
    });
},

修改bottomContainer组件

新增参数接收BottomSheet的刷新方法,并传递给按钮:

Widget bottomContainer(BuildContext context, void Function(void Function()) bottomSheetSetState) {
  return Wrap(
    spacing: 8.0,
    runSpacing: 4.0,
    children: <Widget> [
      ...List.generate(
        listVariant.length,
            (index) => selectedButton(
          index: index,
          text: listVariant[index],
          // 传入BottomSheet的刷新回调
          onTap: () {
            bottomSheetSetState(() {
              _selectedVariant = index;
              print('$index, ${listVariant[index]}');
            });
          },
        ),
      ),
    ],
  );
}

修改selectedButton组件

将点击逻辑改为外部传入的回调:

Widget selectedButton({
  required String text, 
  required int index,
  required VoidCallback onTap, // 新增外部点击回调
}) {
  return InkWell(
    splashColor: Colors.cyanAccent,
    onTap: onTap, // 使用外部传入的刷新逻辑
    child: Container(
        height: 36,
        width: text.length.toDouble() *9,
        decoration: BoxDecoration(
          borderRadius: const BorderRadius.all(Radius.circular(10)),
          border: Border.all(
            width: 1.5,
            color: const Color.fromRGBO(78, 125, 150, 1),
          ),
          color: index == _selectedVariant
              ? const Color.fromRGBO(78, 125, 150, 0.5)
              : Colors.white,
        ),
        child: Center(
          child: Text(text,
            textAlign: TextAlign.center,
            style: const TextStyle(
                color: Color.fromRGBO(78, 125, 150, 1),
                fontSize: 13,
                fontWeight: FontWeight.w700
            ),
          ),
        )
    ),
  );
}

方案2:将BottomSheet抽为独立StatefulWidget

如果BottomSheet逻辑复杂,单独封装组件更清晰,内部维护选中状态并同步给主页面:

独立BottomSheet组件

class VariantBottomSheet extends StatefulWidget {
  final List<String> listVariant;
  final int initialSelected;
  final Function(int) onVariantSelected;

  const VariantBottomSheet({
    super.key,
    required this.listVariant,
    required this.initialSelected,
    required this.onVariantSelected,
  });

  @override
  State<VariantBottomSheet> createState() => _VariantBottomSheetState();
}

class _VariantBottomSheetState extends State<VariantBottomSheet> {
  late int _selectedVariant;

  @override
  void initState() {
    super.initState();
    _selectedVariant = widget.initialSelected;
  }

  @override
  Widget build(BuildContext context) {
    return Wrap(
      spacing: 8.0,
      runSpacing: 4.0,
      children: <Widget>[
        ...List.generate(
          widget.listVariant.length,
              (index) => InkWell(
            splashColor: Colors.cyanAccent,
            onTap: () {
              setState(() {
                _selectedVariant = index;
                widget.onVariantSelected(index); // 同步选中状态到主页面
                print('$index, ${widget.listVariant[index]}');
              });
            },
            child: Container(
              height: 36,
              width: widget.listVariant[index].length.toDouble() *9,
              decoration: BoxDecoration(
                borderRadius: const BorderRadius.all(Radius.circular(10)),
                border: Border.all(
                  width: 1.5,
                  color: const Color.fromRGBO(78, 125, 150, 1),
                ),
                color: index == _selectedVariant
                    ? const Color.fromRGBO(78, 125, 150, 0.5)
                    : Colors.white,
              ),
              child: Center(
                child: Text(widget.listVariant[index],
                  textAlign: TextAlign.center,
                  style: const TextStyle(
                      color: Color.fromRGBO(78, 125, 150, 1),
                      fontSize: 13,
                      fontWeight: FontWeight.w700
                  ),
                ),
              ),
            ),
          ),
        ),
      ],
    );
  }
}

调用独立组件

onPressed: (){
  showModalBottomSheet(
    context: context,
    builder: (BuildContext context) {
      return VariantBottomSheet(
        listVariant: listVariant,
        initialSelected: _selectedVariant,
        onVariantSelected: (index) {
          setState(() {
            _selectedVariant = index; // 同步更新主页面状态
          });
        },
      );
    });
},

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 11:00:55