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

Flutter中ActiveColor与InactiveColor切换功能异常求助

问题描述

我想在BMI计算器的输入页面实现这样的功能:选择MALE时,它的颜色变为activeColor,FEMALE变为inactiveColor;选择FEMALE时则相反。但当前这个功能无法正常工作,尝试用点击事件也没成功。以下是我的InputPage代码:

import 'package:bmi_calculator/result_page.dart';
import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:bmi_calculator/new_widgets.dart';
import 'package:bmi_calculator/constants.dart';
import 'package:bmi_calculator/compute.dart';

const Color activeColor = Color(0xFF1D1E33);
const Color inactiveColor = Color(0xFF111328);
Color maleColor = activeColor;
Color femaleColor = inactiveColor;
int height = 170;
int weight = 80;
int age = 20;

class InputPage extends StatefulWidget {
  @override
  _InputPageState createState() => _InputPageState();
}

class _InputPageState extends State<InputPage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('BMI CALCULATOR'),
        backgroundColor: Color(0XFF070A1A),
      ),
      body: Column(
        children: [
          Expanded(
            child: Row(
              children: [
                Expanded(
                  child: GestureDetector(
                    onTap: (){
                      setState(() {
                        maleColor = activeColor;
                        femaleColor = inactiveColor;
                      });
                    },
                    child: CardWidget(
                      cardColor: maleColor,
                      cardChild: GenderWidget(
                        genderString: 'MALE',
                        genderIcon: FontAwesomeIcons.mars,
                      ),
                    ),
                  ),
                ),
                Expanded(
                  child: GestureDetector(
                    onTap: (){
                      setState(() {
                        maleColor = inactiveColor;
                        femaleColor = activeColor;
                      });
                    },
                    child: CardWidget(
                      cardColor: femaleColor,
                      cardChild: GenderWidget(
                        genderString: 'FEMALE',
                        genderIcon: FontAwesomeIcons.venus,
                      ),
                    ),
                  ),
                ),
              ],
            ),
          ),
          Expanded(
            child: CardWidget(
              cardColor: activeColor,
              cardChild: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Text(
                    'HEIGHT',
                    style: labelStyle,
                  ),
                  Row(
                    mainAxisAlignment: MainAxisAlignment.center,
                    crossAxisAlignment: CrossAxisAlignment.baseline,
                    textBaseline: TextBaseline.alphabetic,
                    children: [
                      Text(
                        height.toString(),
                        style: numberStyle,
                      ),
                      Text(
                        'cm',
                        style: labelStyle,
                      ),
                    ],
                  ),
                  SliderTheme(
                    data: SliderThemeData(
                      inactiveTrackColor: Color(0xff8d8e98),
                      activeTrackColor: Colors.white,
                      thumbColor: Color(0xffeb1555),
                      thumbShape: RoundSliderThumbShape(
                        enabledThumbRadius: 15.0,
                      ),
                      overlayColor: Color(0x29eb1555),
                      overlayShape: RoundSliderOverlayShape(
                        overlayRadius: 30.0,
                      ),
                    ),
                    child: Slider(
                      min: 120,
                      max: 220,
                      value: height.toDouble(),
                      onChanged: (double newValue){
                        setState(() {
                          height = newValue.round();
                        });
                      },
                    ),
                  ),
                ],
              ),
            ),
          ),
          Expanded(
            child: Row(
              children: [
                Expanded(
                  child: CardWidget(
                    cardColor: activeColor,
                    cardChild: Column(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: [
                        Text(
                          'WEIGHT',
                          style: labelStyle,
                        ),
                        Text(
                          weight.toString(),
                          style: numberStyle,
                        ),
                        Row(
                          mainAxisAlignment: MainAxisAlignment.center,
                          children: [
                            ButtonWidget(
                              buttonIcon: FontAwesomeIcons.minus,
                              buttonFunction: (){
                                setState(() {
                                  weight--;
                                });
                              },
                            ),
                            SizedBox(
                              width: 10.0,
                            ),
                            ButtonWidget(
                              buttonIcon: FontAwesomeIcons.plus,
                              buttonFunction: (){
                                setState(() {
                                  weight++;
                                });
                              },
                            ),
                          ],
                        ),
                      ],
                    ),
                  ),
                ),
                Expanded(
                  child: CardWidget(
                    cardColor: activeColor,
                    cardChild: Column(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: [
                        Text(
                          'AGE',
                          style: labelStyle,
                        ),
                        Text(
                          age.toString(),
                          style: numberStyle,
                        ),
                        Row(
                          mainAxisAlignment: MainAxisAlignment.center,
                          children: [
                            ButtonWidget(
                              buttonIcon: FontAwesomeIcons.minus,
                              buttonFunction: (){
                                setState(() {
                                  age--;
                                });
                              },
                            ),
                            SizedBox(
                              width: 10.0,
                            ),
                            ButtonWidget(
                              buttonIcon: FontAwesomeIcons.plus,
                              buttonFunction: (){
                                setState(() {
                                  age++;
                                });
                              },
                            ),
                          ],
                        ),
                      ],
                    ),
                  ),
                ),
              ],
            ),
          ),
          CalculateWidget(
            calcFunction: (){
              Compute calc = new Compute(height, weight);
              String bmi = calc.getBMI();
              String result = calc.getResult();
              String interpret = calc.getInterpretation();

              Navigator.push(context, MaterialPageRoute(builder: (context){
                return ResultPage(bmi: bmi, bmiresu: result, bmiinter: interpret);
              }));
            },
            calcString: 'CALCULATE',
          ),
        ],
      ),
    );
  }
}
修复方案

问题出在你把状态变量(maleColor、femaleColor、height等)定义成了全局变量,Flutter的setState只能管理State类内部的状态,全局变量的更新不会触发UI重建。

把这些变量移到_InputPageState类内部即可解决问题,修改后的完整代码如下:

import 'package:bmi_calculator/result_page.dart';
import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:bmi_calculator/new_widgets.dart';
import 'package:bmi_calculator/constants.dart';
import 'package:bmi_calculator/compute.dart';

const Color activeColor = Color(0xFF1D1E33);
const Color inactiveColor = Color(0xFF111328);

class InputPage extends StatefulWidget {
  @override
  _InputPageState createState() => _InputPageState();
}

class _InputPageState extends State<InputPage> {
  // 将状态变量移到State类内部
  Color maleColor = activeColor;
  Color femaleColor = inactiveColor;
  int height = 170;
  int weight = 80;
  int age = 20;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('BMI CALCULATOR'),
        backgroundColor: Color(0XFF070A1A),
      ),
      body: Column(
        children: [
          Expanded(
            child: Row(
              children: [
                Expanded(
                  child: GestureDetector(
                    onTap: (){
                      setState(() {
                        maleColor = activeColor;
                        femaleColor = inactiveColor;
                      });
                    },
                    child: CardWidget(
                      cardColor: maleColor,
                      cardChild: GenderWidget(
                        genderString: 'MALE',
                        genderIcon: FontAwesomeIcons.mars,
                      ),
                    ),
                  ),
                ),
                Expanded(
                  child: GestureDetector(
                    onTap: (){
                      setState(() {
                        maleColor = inactiveColor;
                        femaleColor = activeColor;
                      });
                    },
                    child: CardWidget(
                      cardColor: femaleColor,
                      cardChild: GenderWidget(
                        genderString: 'FEMALE',
                        genderIcon: FontAwesomeIcons.venus,
                      ),
                    ),
                  ),
                ),
              ],
            ),
          ),
          Expanded(
            child: CardWidget(
              cardColor: activeColor,
              cardChild: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Text(
                    'HEIGHT',
                    style: labelStyle,
                  ),
                  Row(
                    mainAxisAlignment: MainAxisAlignment.center,
                    crossAxisAlignment: CrossAxisAlignment.baseline,
                    textBaseline: TextBaseline.alphabetic,
                    children: [
                      Text(
                        height.toString(),
                        style: numberStyle,
                      ),
                      Text(
                        'cm',
                        style: labelStyle,
                      ),
                    ],
                  ),
                  SliderTheme(
                    data: SliderThemeData(
                      inactiveTrackColor: Color(0xff8d8e98),
                      activeTrackColor: Colors.white,
                      thumbColor: Color(0xffeb1555),
                      thumbShape: RoundSliderThumbShape(
                        enabledThumbRadius: 15.0,
                      ),
                      overlayColor: Color(0x29eb1555),
                      overlayShape: RoundSliderOverlayShape(
                        overlayRadius: 30.0,
                      ),
                    ),
                    child: Slider(
                      min: 120,
                      max: 220,
                      value: height.toDouble(),
                      onChanged: (double newValue){
                        setState(() {
                          height = newValue.round();
                        });
                      },
                    ),
                  ),
                ],
              ),
            ),
          ),
          Expanded(
            child: Row(
              children: [
                Expanded(
                  child: CardWidget(
                    cardColor: activeColor,
                    cardChild: Column(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: [
                        Text(
                          'WEIGHT',
                          style: labelStyle,
                        ),
                        Text(
                          weight.toString(),
                          style: numberStyle,
                        ),
                        Row(
                          mainAxisAlignment: MainAxisAlignment.center,
                          children: [
                            ButtonWidget(
                              buttonIcon: FontAwesomeIcons.minus,
                              buttonFunction: (){
                                setState(() {
                                  weight--;
                                });
                              },
                            ),
                            SizedBox(
                              width: 10.0,
                            ),
                            ButtonWidget(
                              buttonIcon: FontAwesomeIcons.plus,
                              buttonFunction: (){
                                setState(() {
                                  weight++;
                                });
                              },
                            ),
                          ],
                        ),
                      ],
                    ),
                  ),
                ),
                Expanded(
                  child: CardWidget(
                    cardColor: activeColor,
                    cardChild: Column(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: [
                        Text(
                          'AGE',
                          style: labelStyle,
                        ),
                        Text(
                          age.toString(),
                          style: numberStyle,
                        ),
                        Row(
                          mainAxisAlignment: MainAxisAlignment.center,
                          children: [
                            ButtonWidget(
                              buttonIcon: FontAwesomeIcons.minus,
                              buttonFunction: (){
                                setState(() {
                                  age--;
                                });
                              },
                            ),
                            SizedBox(
                              width: 10.0,
                            ),
                            ButtonWidget(
                              buttonIcon: FontAwesomeIcons.plus,
                              buttonFunction: (){
                                setState(() {
                                  age++;
                                });
                              },
                            ),
                          ],
                        ),
                      ],
                    ),
                  ),
                ),
              ],
            ),
          ),
          CalculateWidget(
            calcFunction: (){
              Compute calc = Compute(height, weight);
              String bmi = calc.getBMI();
              String result = calc.getResult();
              String interpret = calc.getInterpretation();

              Navigator.push(context, MaterialPageRoute(builder: (context){
                return ResultPage(bmi: bmi, bmiresu: result, bmiinter: interpret);
              }));
            },
            calcString: 'CALCULATE',
          ),
        ],
      ),
    );
  }
}

关键修改点

  • 把maleColor、femaleColor、height、weight、age从全局变量移到_InputPageState类中作为成员变量
  • 保留原来的GestureDetector点击逻辑,现在setState会正确标记状态变更并触发UI重建
  • 现在点击MALE或FEMALE卡片时,颜色会按预期切换

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 02:15:40