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

Flutter GridView按钮单选切换颜色实现方法问询

输出界面

This is the output screen
兴趣选择界面

需求与问题

现有基于Flutter实现的GridView兴趣选择界面,需实现以下单选交互:

  • 点击任意按钮时,该按钮变为金色样式,其余按钮保持原有状态
  • 再次点击已选中的按钮,恢复其正常颜色,取消选择
  • 全程仅支持单选一个按钮
实现方案

核心思路

  1. 定义状态变量存储当前选中的兴趣项标识(ID或索引)
  2. 点击按钮时更新选中状态:已选中则取消,未选中则切换为当前项
  3. 根据选中状态动态渲染按钮的样式(背景/边框颜色等)

修改后的完整代码片段

// 在State类中添加选中状态变量
String? selectedInterestId;

return Scaffold(
  body: SafeArea(
    child: SingleChildScrollView(
      physics: const BouncingScrollPhysics(),
      child: Column(
        children: [
          Container(
            height: MediaQuery.of(context).size.height,
            width: MediaQuery.of(context).size.width,
            decoration: BoxDecoration(
              image: const DecorationImage(
                image: AssetImage('assets/images/frame.png'),
                fit: BoxFit.fill),
              color: AppColors.purewhite),
            child: SingleChildScrollView(
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  GestureDetector(
                    onTap: () {
                      Get.to(GenderScreen());
                    },
                    child: Padding(
                      padding: const EdgeInsets.all(15.0),
                      child: Icon(Icons.arrow_back_ios_new,
                          color: AppColors.textgreen),
                    ),
                  ),
                  Column(children: [
                    const Padding(
                      padding: EdgeInsets.symmetric(vertical: 20),
                      child: CustomIcon(
                        svgIcon: 'assets/images/fourstep.svg',
                        size: 150)),
                    Row(
                      children: [
                        Padding(
                          padding: const EdgeInsets.only(top: 20, left: 20),
                          child: Text('Your Interests', style: logintext),
                        ),
                      ],
                    ),
                    FutureBuilder(
                      future: Get.put(APIService(Dio())).getInterest(token),
                      builder: (context, AsyncSnapshot<ListModel> snapshot) {
                        if (!snapshot.hasData) {
                          if (snapshot.connectionState == ConnectionState.waiting) {
                            return const Center(child: CircularProgressIndicator());
                          }
                          if (snapshot.hasError) {
                            return Container(child: Text(snapshot.error.toString()));
                          }
                          return const SizedBox();
                        }

                        return SingleChildScrollView(
                          physics: const BouncingScrollPhysics(),
                          child: Padding(
                            padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 10),
                            child: SizedBox(
                              height: 120,
                              child: GridView.builder(
                                itemCount: snapshot.data!.data!.length,
                                scrollDirection: Axis.vertical,
                                gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
                                  crossAxisCount: 3,
                                  childAspectRatio: 4 / 2),
                                itemBuilder: (BuildContext context, int index) {
                                  Data data = snapshot.data!.data![index];
                                  String currentId = data.id.toString();
                                  bool isSelected = selectedInterestId == currentId;

                                  return InkWell(
                                    onTap: () {
                                      setState(() {
                                        // 更新选中状态:点击已选中项则取消,否则选中当前项
                                        selectedInterestId = isSelected ? null : currentId;
                                      });
                                    },
                                    child: Container(
                                      margin: const EdgeInsets.symmetric(vertical: 10, horizontal: 5),
                                      decoration: BoxDecoration(
                                        // 动态设置背景色:选中时金色,未选中时白色
                                        color: isSelected ? AppColors.golden : AppColors.purewhite,
                                        border: Border.all(
                                          color: AppColors.golden,
                                          width: 3),
                                        borderRadius: const BorderRadius.all(Radius.circular(20))),
                                      padding: const EdgeInsets.all(1),
                                      child: Center(
                                        child: Text(
                                          data.interest.toString(),
                                          style: TextStyle(
                                            fontSize: 25,
                                            // 可选:选中时文字改为白色,增强对比度
                                            color: isSelected ? AppColors.purewhite : Colors.black),
                                        ),
                                      ),
                                    ),
                                  );
                                },
                              ),
                            ),
                          ),
                        );
                      },
                    ),
                  ]),
                ],
              ),
            ),
          ),
        ],
      ),
    ),
  ),
);

补充说明

  • 若AppColors未定义golden,需添加对应颜色值,例如static const Color golden = Color(0xFFFFD700);
  • 可根据设计需求调整选中样式:比如仅修改边框粗细/颜色,而非背景色
  • 如果需要用索引判断选中状态,可将selectedInterestId替换为int? selectedIndex,逻辑保持一致

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 17:07:33