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

Flutter技术问题:仅修改点击按钮颜色并批量禁用按钮

解决Flutter德语冠词按钮点击后全部变色禁用的问题

嘿,我明白你现在遇到的困扰了——点击任意一个按钮后,三个按钮都会一起变色并禁用,这显然不是你想要的效果。问题的核心在于所有按钮共用了同一个全局状态变量,咱们一步步来修复它:

问题根源分析

你当前的代码里,enabled和bgColor是父组件的全局变量,三个ArticleButton都绑定了这两个值。所以只要调用setState修改它们,所有按钮都会同步变化,自然就出现了全变色、全禁用的情况。

每个按钮应该拥有独立的状态:比如自己是否被点击过、自己的显示颜色,而不是依赖父组件的全局变量。

解决方案代码修改

第一步:重构ArticleButton为有状态组件

把原本的StatelessWidget改成StatefulWidget,让每个按钮自己维护点击状态和颜色:

import 'package:flutter/material.dart';

class ArticleButton extends StatefulWidget {
  final String article;
  final bool isCorrect;
  final VoidCallback? onPressed;

  // 构造函数使用required标记必填参数(Flutter 2.0+推荐写法)
  const ArticleButton({
    Key? key,
    required this.article,
    required this.isCorrect,
    required this.onPressed,
  }) : super(key: key);

  @override
  _ArticleButtonState createState() => _ArticleButtonState();
}

class _ArticleButtonState extends State<ArticleButton> {
  bool _hasBeenPressed = false;

  @override
  Widget build(BuildContext context) {
    // 按钮颜色逻辑:未点击时默认蓝色,点击后根据是否正确显示绿/红
    Color buttonColor = Colors.blue;
    if (_hasBeenPressed) {
      buttonColor = widget.isCorrect ? Colors.green : Colors.red;
    }

    return Padding(
      padding: const EdgeInsets.all(8.0),
      child: FlatButton(
        // 点击后禁用自身,同时触发父组件的回调
        onPressed: _hasBeenPressed || widget.onPressed == null 
            ? null 
            : () {
                setState(() {
                  _hasBeenPressed = true;
                });
                widget.onPressed!();
              },
        child: Text(
          widget.article,
          style: const TextStyle(
            fontSize: 20.0,
            fontFamily: 'Roboto',
          ),
        ),
        splashColor: Colors.grey,
        color: buttonColor,
        disabledColor: buttonColor,
      ),
    );
  }
}

第二步:修改主页面逻辑,移除全局状态变量

在父组件里只维护全局的得分、当前题目索引,以及是否允许点击按钮的全局开关:

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'services/word.dart';
import 'package:germanarticle/button.dart';

void main() {
  runApp(const MaterialApp(
    home: Home(),
  ));
}

class Home extends StatefulWidget {
  const Home({Key? key}) : super(key: key);

  @override
  _HomeState createState() => _HomeState();
}

class _HomeState extends State<Home> {
  final List<Word> words = [
    Word(article: "Der", word: "Apfel"),
    Word(article: "Die", word: "Erdbeere"),
    Word(article: "Das", word: "Auto"),
  ];
  final List<String> articles = ['Der', "Die", "Das"];
  int index = 0;
  int score = 0;
  // 标记是否已经有按钮被点击,用来禁用所有按钮
  bool _isAnswered = false;

  // 处理按钮点击后的全局逻辑
  void _onButtonTap(bool isCorrect) {
    setState(() {
      _isAnswered = true;
      if (isCorrect) score++;
    });
  }

  // 切换到下一题,重置状态
  void _nextWord() {
    setState(() {
      index++;
      _isAnswered = false;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          Text("$score"),
          Text(words[index].word, style: const TextStyle(
            fontSize: 60.0,
          ),),
          const SizedBox(height: 20.0),
          Row(
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            children: articles.map((e) => ArticleButton(
              article: e,
              isCorrect: words[index].article == e,
              onPressed: _isAnswered ? null : () => _onButtonTap(words[index].article == e),
            )).toList(),
          ),
          FlatButton(
            onPressed: _nextWord,
            child: const Text("next"),
          )
        ],
      ),
    );
  }
}

关键修改点说明

  1. 按钮独立状态:每个ArticleButton自己管理_hasBeenPressed变量,点击后只改变自身的颜色和禁用状态,不会影响其他按钮。
  2. 全局开关控制:父组件用_isAnswered变量确保一旦有按钮被点击,所有按钮都会被禁用,避免重复点击。
  3. 职责分离:按钮只负责自己的UI状态,得分计算、题目切换等全局逻辑交给父组件处理,符合OOP的单一职责原则。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 16:27:58