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

Flutter咖啡商城:如何将Toggle Button选中数据传入购物车

解决方案

要把Toggle Button的选中数据传递到购物车页面,核心是让详情页(父组件)获取Toggle组件(子组件)的选中状态,再将这些状态和咖啡商品信息一起加入购物车,最终在购物车页面展示。具体步骤如下:

1. 修改Toggle组件,向外暴露选中状态

让WholeOrGround和OneTimeSubscribe通过回调函数把选中值传递给父组件,而非封闭维护状态:

修改WholeOrGround组件

class WholeOrGround extends StatefulWidget {
  // 定义回调,传递选中的研磨方式
  final ValueChanged<String> onGrindSelected;
  // 可选:设置默认选中值
  final String initialValue;

  const WholeOrGround({
    Key? key,
    required this.onGrindSelected,
    this.initialValue = 'Whole Bean',
  }) : super(key: key);

  @override
  State<WholeOrGround> createState() => _WholeOrGround();
}

class _WholeOrGround extends State<WholeOrGround> {
  late List<bool> isSelected;

  @override
  void initState() {
    super.initState();
    // 根据初始值初始化选中状态
    isSelected = [
      widget.initialValue == 'Whole Bean',
      widget.initialValue == 'Ground'
    ];
  }

  @override
  Widget build(BuildContext context) {
    return ToggleButtons(
      color: Colors.amber,
      borderColor: Colors.amber,
      splashColor: const Color.fromARGB(255, 251, 187, 208),
      borderWidth: 3,
      borderRadius: BorderRadius.circular(10),
      selectedColor: Colors.lightBlue,
      onPressed: (int newIndex) {
        setState(() {
          for (int index = 0; index < isSelected.length; index++) {
            isSelected[index] = index == newIndex;
          }
        });
        // 通过回调传递选中值
        final selectedGrind = newIndex == 0 ? 'Whole Bean' : 'Ground';
        widget.onGrindSelected(selectedGrind);
      },
      isSelected: isSelected,
      children: const [
        Padding(
            padding: EdgeInsets.all(4),
            child: Text('Whole Bean',
                style: TextStyle(fontWeight: FontWeight.bold))),
        Padding(
          padding: EdgeInsets.all(4),
          child: Text('Ground', style: TextStyle(fontWeight: FontWeight.bold)),
        )
      ],
    );
  }
}

同理修改OneTimeSubscribe组件

class OneTimeSubscribe extends StatefulWidget {
  final ValueChanged<String> onPaymentSelected;
  final String initialValue;

  const OneTimeSubscribe({
    Key? key,
    required this.onPaymentSelected,
    this.initialValue = 'one-time payment',
  }) : super(key: key);

  @override
  State<OneTimeSubscribe> createState() => _OneTimeSubscribe();
}

class _OneTimeSubscribe extends State<OneTimeSubscribe> {
  late List<bool> isSelected;

  @override
  void initState() {
    super.initState();
    isSelected = [
      widget.initialValue == 'one-time payment',
      widget.initialValue == 'subscription'
    ];
  }

  @override
  Widget build(BuildContext context) {
    return ToggleButtons(
      // 保留原有样式设置
      onPressed: (int newIndex) {
        setState(() {
          for (int index = 0; index < isSelected.length; index++) {
            isSelected[index] = index == newIndex;
          }
        });
        final selectedPayment = newIndex == 0 ? 'one-time payment' : 'subscription';
        widget.onPaymentSelected(selectedPayment);
      },
      isSelected: isSelected,
      children: const [
        Padding(
            padding: EdgeInsets.all(4),
            child: Text('One-Time Payment',
                style: TextStyle(fontWeight: FontWeight.bold))),
        Padding(
          padding: EdgeInsets.all(4),
          child: Text('Subscription', style: TextStyle(fontWeight: FontWeight.bold)),
        )
      ],
    );
  }
}

2. 在详情页父组件中接收选中状态

在详情页声明变量存储研磨方式和支付类型,通过回调获取Toggle组件的选中值:

class CoffeeDetailPage extends StatefulWidget {
  final CoffeeItem coffee; // 当前展示的咖啡商品
  const CoffeeDetailPage({Key? key, required this.coffee}) : super(key: key);

  @override
  State<CoffeeDetailPage> createState() => _CoffeeDetailPageState();
}

class _CoffeeDetailPageState extends State<CoffeeDetailPage> {
  final _formKey = GlobalKey<FormState>();
  String _selectedGrind = 'Whole Bean';
  String _selectedPayment = 'one-time payment';

  // 添加到购物车的方法
  void addToCart() {
    // 创建包含选中状态的购物车项(需先修改CoffeeItem模型)
    final cartItem = CoffeeItem(
      title: widget.coffee.title,
      productPrice: widget.coffee.productPrice,
      image: widget.coffee.image,
      grindSetting: _selectedGrind,
      paymentType: _selectedPayment,
    );
    // 调用你的购物车添加逻辑(比如Provider、Bloc等状态管理方式)
    // 示例:Provider.of<CartProvider>(context, listen: false).addItem(cartItem);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      // 其他页面内容...
      Form(
        key: _formKey,
        child: Column(
          children: [
            WholeOrGround(
              onGrindSelected: (grind) {
                setState(() {
                  _selectedGrind = grind;
                });
              },
              initialValue: _selectedGrind,
            ),
            const SizedBox(height: 15),
            OneTimeSubscribe(
              onPaymentSelected: (payment) {
                setState(() {
                  _selectedPayment = payment;
                });
              },
              initialValue: _selectedPayment,
            ),
            const SizedBox(height: 15),
            ElevatedButton(
              onPressed: addToCart,
              child: const Text('Add to Cart'),
            )
          ],
        ),
      ),
    );
  }
}

3. 修改CoffeeItem模型,新增字段存储选中状态

确保模型包含研磨方式和支付类型字段:

class CoffeeItem {
  final String title;
  final String productPrice;
  final String image;
  final String grindSetting; // 新增字段
  final String paymentType; // 新增字段

  CoffeeItem({
    required this.title,
    required this.productPrice,
    required this.image,
    required this.grindSetting,
    required this.paymentType,
  });
}

4. 在购物车页面展示选中的数据

修改购物车列表项,展示研磨方式和支付类型:

Expanded(
  child: ListView.builder(
    itemCount: value.cart.length,
    itemBuilder: (context, index) {
      final CoffeeItem coffeeItem = value.cart[index];
      final String coffeeTitle = coffeeItem.title;
      final String coffeePrice = coffeeItem.productPrice;
      final String coffeeImage = coffeeItem.image;
      // 直接从购物车项中获取选中的数据
      final String grindSetting = coffeeItem.grindSetting;
      final String paymentType = coffeeItem.paymentType;

      return Container(
        decoration: BoxDecoration(
            borderRadius: BorderRadius.circular(15),
            color: const Color.fromARGB(255, 219, 176, 243)),
        margin: const EdgeInsets.only(left: 20, top: 20, right: 20),
        child: ListTile(
          leading: Image.asset(coffeeImage),
          title: Text(coffeeTitle),
          subtitle: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Text('\$$coffeePrice'),
              Text('研磨方式: $grindSetting'),
              Text('支付类型: $paymentType'),
            ],
          ),
          trailing: IconButton(
              onPressed: () => removeFromCart(coffeeItem, context),
              icon: const Icon(Icons.delete)),
        ),
      );
    },
  ),
)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 00:06:20