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

如何在SingleChildScrollView中管理自定义卡片的选中状态

实现卡片单选选中效果的解决方案

以下是针对需求修改后的代码,实现点击卡片切换样式(背景色、边框色)、添加底部绿色匹配宽度方块,且保持单选状态:

修改后的CategoryCard组件

import 'package:flutter/material.dart';

class CategoryCard extends StatelessWidget {
  final String? categoryCardName;
  final Function()? wasPressed;
  final bool isSelected; // 标记当前卡片是否选中

  const CategoryCard({
    super.key,
    required this.categoryCardName,
    this.wasPressed,
    required this.isSelected,
  });

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: wasPressed,
      child: Card(
        elevation: isSelected ? 2 : 0, // 选中时添加轻微阴影增强视觉效果
        shape: RoundedRectangleBorder(
          side: BorderSide(
            color: isSelected ? Colors.green : const Color.fromRGBO(212, 213, 215, 1),
            width: 3,
          ),
          borderRadius: BorderRadius.circular(20.0),
        ),
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            Container(
              decoration: BoxDecoration(
                color: isSelected ? Colors.green.shade50 : const Color.fromRGBO(242, 243, 243, 1),
                borderRadius: const BorderRadius.vertical(top: Radius.circular(20.0)),
              ),
              padding: const EdgeInsets.all(10),
              child: Text(
                categoryCardName ?? 'Todas',
                style: TextStyle(
                  fontSize: 25,
                  fontWeight: FontWeight.bold,
                  color: isSelected ? Colors.green : const Color.fromRGBO(91, 94, 99, 1),
                ),
              ),
            ),
            // 选中时显示底部绿色方块,宽度匹配卡片
            if (isSelected)
              Container(
                height: 4,
                width: double.infinity,
                decoration: const BoxDecoration(
                  color: Colors.green,
                  borderRadius: BorderRadius.vertical(bottom: Radius.circular(20.0)),
                ),
              ),
          ],
        ),
      ),
    );
  }
}

修改后的MyHomePage页面

import 'package:flutter/material.dart';
import 'category_card.dart';
import 'category_card_model.dart';

class MyHomePage extends StatefulWidget {
  MyHomePage({super.key, required this.title});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final categoryCardModelList = <CategoryCardModel>[
    CategoryCardModel("Todas"),
    CategoryCardModel("Smartphones"),
    CategoryCardModel("Accesorios para celular"),
    CategoryCardModel("TV")
  ];

  List<CategoryCardModel>? _categoryCardModelListOf;
  CategoryCardModel? _selectedCategory; // 跟踪当前选中的卡片

  @override
  void initState() {
    super.initState();
    _categoryCardModelListOf = List.of(categoryCardModelList);
    // 可选:默认选中第一个卡片
    _selectedCategory = _categoryCardModelListOf?.first;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: SingleChildScrollView(
        scrollDirection: Axis.horizontal,
        padding: const EdgeInsets.fromLTRB(10.0, 0.0, 10.0, 0.0),
        child: Row(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: _categoryCardModelListOf!
              .map<Widget>((categoryCardModel) => CategoryCard(
                    wasPressed: () {
                      setState(() {
                        _selectedCategory = categoryCardModel; // 更新选中状态
                      });
                    },
                    categoryCardName: categoryCardModel.categoryCardModelName,
                    isSelected: _selectedCategory == categoryCardModel, // 传递选中状态
                  ))
              .toList(),
        ),
      ),
    );
  }
}

关键改动说明

  1. 选中状态跟踪:在页面状态类中新增_selectedCategory变量,用于记录当前选中的卡片模型,确保单选逻辑。
  2. 动态样式控制:给CategoryCard添加isSelected参数,根据该参数切换边框色、背景色、文字颜色,选中时使用绿色系样式。
  3. 底部绿色方块:将卡片内部布局改为Column,在底部添加绿色容器,仅在选中时显示,宽度设为double.infinity以匹配卡片宽度,圆角与卡片保持一致。
  4. 单选逻辑实现:点击卡片时通过setState更新_selectedCategory,触发UI刷新,保证同一时间只有一个卡片处于选中状态。

内容的提问来源于stack exchange,提问作者MATEO VALENCIA MINOTA

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 15:25:19