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

Flutter长按按钮状态切换问题:按压显示内容,松开恢复原状

问题分析与修复方案

核心问题

  1. 全局变量无法触发UI更新:你定义的chosen1到chosen8是全局变量,修改它们的值不会调用setState(),Flutter无法感知状态变化,自然不会更新UI。
  2. UI未绑定状态变量:灯光的颜色是固定白色,没有根据chosen变量动态切换样式。
  3. 未在松开按钮时重置状态:onTapUp里没有把chosen变量重置为false,也没触发UI刷新。

修复步骤

  • 把所有状态变量(chosen1-chosen8、ver、lightsIndex)移到_LBulb State类内部,确保状态变化能触发setState。
  • 让灯光的颜色根据对应的chosen变量动态切换(比如选中时变黄色,未选中时白色)。
  • 在onTapDown中设置chosen变量后调用setState()刷新UI;在onTapUp中重置chosen变量并再次调用setState()。
  • 移除全局变量,避免状态管理混乱。

修改后的完整代码

import 'dart:math';
import 'package:flutter/material.dart';
import 'globals.dart' as globals;

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      debugShowCheckedModeBanner: false,
      home: LBulb(),
    );
  }
}

class LBulb extends StatefulWidget {
  const LBulb({super.key});

  @override
  State<LBulb> createState() => _LBulbState();
}

class _LBulbState extends State<LBulb> {
  final stopwatchD = Stopwatch();
  final stopwatchR = Stopwatch();
  late bool chosen1;
  late bool chosen2;
  late bool chosen3;
  late bool chosen4;
  late bool chosen5;
  late bool chosen6;
  late bool chosen7;
  late bool chosen8;
  late int ver;
  late List<int> lightsIndex;

  @override
  void initState() {
    super.initState();
    resetChosenStates();
    ver = oneOrThree();
    lightsIndex = randomLights(ver);
  }

  void resetChosenStates() {
    setState(() {
      chosen1 = false;
      chosen2 = false;
      chosen3 = false;
      chosen4 = false;
      chosen5 = false;
      chosen6 = false;
      chosen7 = false;
      chosen8 = false;
    });
  }

  @override
  Widget build(BuildContext context) {
    print(lightsIndex);
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Colors.blue[600]?.withOpacity(0.5),
      ),
      body: Container(
        decoration: const BoxDecoration(
          image: DecorationImage(
              image: AssetImage("assets/images/background2.png"),
              fit: BoxFit.cover),
        ),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            const SizedBox(height: 60),
            const Text(
              "请点击并按住对应灯光的按钮",
              textAlign: TextAlign.center,
              style: TextStyle(
                  color: Colors.black,
                  fontSize: 40,
                  fontWeight: FontWeight.bold,
                  fontFamily: 'Alkatra'),
            ),
            const SizedBox(height: 30),
            Center(
              child: Container(
                height: 500,
                width: 810,
                decoration: BoxDecoration(
                  color: Colors.white,
                  borderRadius: BorderRadius.circular(100),
                  boxShadow: [
                    BoxShadow(
                      color: Colors.black.withOpacity(0.5),
                      offset: const Offset(7.0, 7.0),
                      blurRadius: 10.0,
                    ),
                  ],
                ),
                child: screenBuilding(
                  distance: 310.0,
                  // 中心按钮
                  centerButton: GestureDetector(
                    onTapDown: (details) {
                      stopwatchD.start();
                      setState(() {
                        for (int index in lightsIndex) {
                          switch (index) {
                            case 1: chosen1 = true; break;
                            case 2: chosen2 = true; break;
                            case 3: chosen3 = true; break;
                            case 4: chosen4 = true; break;
                            case 5: chosen5 = true; break;
                            case 6: chosen6 = true; break;
                            case 7: chosen7 = true; break;
                            case 8: chosen8 = true; break;
                          }
                        }
                      });
                    },
                    onTapUp: (details) {
                      stopwatchD.stop();
                      globals.detectionTime = stopwatchD.elapsed;
                      globals.detectionTimes[globals.numOfTurn] = globals.detectionTime;
                      stopwatchD.reset();
                      globals.detectionTime = const Duration(seconds: 0);
                      globals.numOfTurn++;
                      print(globals.detectionTimes);
                      stopwatchR.start();
                      // 重置灯光状态
                      resetChosenStates();
                    },
                    onTapCancel: () {
                      // 处理意外取消点击的情况(比如滑动离开按钮)
                      resetChosenStates();
                    },
                    child: Container(
                      height: 20,
                      width: 20,
                      decoration: BoxDecoration(
                          color: Colors.black,
                          borderRadius: BorderRadius.circular(500)),
                    ),
                  ),
                  // 灯光按钮(第一行)
                  buttonsFirstRow: [
                    TextButton(
                      onPressed: () => print("clicked1"),
                      child: Container(
                        height: 20,
                        width: 20,
                        decoration: BoxDecoration(
                            color: Colors.black,
                            borderRadius: BorderRadius.circular(500)),
                      ),
                    ),
                    TextButton(
                      onPressed: () => print("clicked2"),
                      child: Container(
                        height: 20,
                        width: 20,
                        decoration: BoxDecoration(
                            color: Colors.black,
                            borderRadius: BorderRadius.circular(500)),
                      ),
                    ),
                    TextButton(
                      onPressed: () => print("clicked3"),
                      child: Container(
                        height: 20,
                        width: 20,
                        decoration: BoxDecoration(
                            color: Colors.black,
                            borderRadius: BorderRadius.circular(500)),
                      ),
                    ),
                    TextButton(
                      onPressed: () => print("clicked4"),
                      child: Container(
                        height: 20,
                        width: 20,
                        decoration: BoxDecoration(
                            color: Colors.black,
                            borderRadius: BorderRadius.circular(500)),
                      ),
                    ),
                    TextButton(
                      onPressed: () => print("clicked5"),
                      child: Container(
                        height: 20,
                        width: 20,
                        decoration: BoxDecoration(
                            color: Colors.black,
                            borderRadius: BorderRadius.circular(500)),
                      ),
                    ),
                    TextButton(
                      onPressed: () => print("clicked6"),
                      child: Container(
                        height: 20,
                        width: 20,
                        decoration: BoxDecoration(
                            color: Colors.black,
                            borderRadius: BorderRadius.circular(500)),
                      ),
                    ),
                    TextButton(
                      onPressed: () => print("clicked7"),
                      child: Container(
                        height: 20,
                        width: 20,
                        decoration: BoxDecoration(
                            color: Colors.black,
                            borderRadius: BorderRadius.circular(500)),
                      ),
                    ),
                    TextButton(
                      onPressed: () => print("clicked8"),
                      child: Container(
                        height: 20,
                        width: 20,
                        decoration: BoxDecoration(
                            color: Colors.black,
                            borderRadius: BorderRadius.circular(500)),
                      ),
                    ),
                  ],
                  // 第一组灯光(4个)
                  buttonsSecondRowHalf1: [
                    TextButton(
                      onPressed: () {},
                      child: Container(
                        height: 20,
                        width: 20,
                        decoration: BoxDecoration(
                            color: chosen1 ? Colors.yellow : Colors.white,
                            borderRadius: BorderRadius.circular(500),
                            border: Border.all(width: 3)),
                      ),
                    ),
                    TextButton(
                      onPressed: () {},
                      child: Container(
                        height: 20,
                        width: 20,
                        decoration: BoxDecoration(
                            color: chosen2 ? Colors.yellow : Colors.white,
                            borderRadius: BorderRadius.circular(500),
                            border: Border.all(width: 3)),
                      ),
                    ),
                    TextButton(
                      onPressed: () {},
                      child: Container(
                        height: 20,
                        width: 20,
                        decoration: BoxDecoration(
                            color: chosen3 ? Colors.yellow : Colors.white,
                            borderRadius: BorderRadius.circular(500),
                            border: Border.all(width: 3)),
                      ),
                    ),
                    TextButton(
                      onPressed: () {},
                      child: Container(
                        height: 20,
                        width: 20,
                        decoration: BoxDecoration(
                            color: chosen4 ? Colors.yellow : Colors.white,
                            borderRadius: BorderRadius.circular(500),
                            border: Border.all(width: 3)),
                      ),
                    ),
                  ],
                  // 第二组灯光(4个)
                  buttonsSecondRowHalf2: [
                    TextButton(
                      onPressed: () {},
                      child: Container(
                        height: 20,
                        width: 20,
                        decoration: BoxDecoration(
                            color: chosen5 ? Colors.yellow : Colors.white,
                            borderRadius: BorderRadius.circular(500),
                            border: Border.all(width: 3)),
                      ),
                    ),
                    TextButton(
                      onPressed: () {},
                      child: Container(
                        height: 20,
                        width: 20,
                        decoration: BoxDecoration(
                            color: chosen6 ? Colors.yellow : Colors.white,
                            borderRadius: BorderRadius.circular(500),
                            border: Border.all(width: 3)),
                      ),
                    ),
                    TextButton(
                      onPressed: () {},
                      child: Container(
                        height: 20,
                        width: 20,
                        decoration: BoxDecoration(
                            color: chosen7 ? Colors.yellow : Colors.white,
                            borderRadius: BorderRadius.circular(500),
                            border: Border.all(width: 3)),
                      ),
                    ),
                    TextButton(
                      onPressed: () {},
                      child: Container(
                        height: 20,
                        width: 20,
                        decoration: BoxDecoration(
                            color: chosen8 ? Colors.yellow : Colors.white,
                            borderRadius: BorderRadius.circular(500),
                            border: Border.all(width: 3)),
                      ),
                    ),
                  ],
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }

  int oneOrThree() {
    final rand = Random();
    List<int> a = [1, 3];
    return a[rand.nextInt(a.length)];
  }

  List<int> randomLights(int ver) {
    final rand = Random();
    List<int> a = [1, 2, 3, 4, 5, 6, 7, 8];
    List<int> ans = [];
    if (ver == 1) {
      int temp = a[rand.nextInt(a.length)];
      ans.add(temp);
    } else {
      int temp1 = a[rand.nextInt(a.length)];
      a.remove(temp1);
      ans.add(temp1);
      int temp2 = a[rand.nextInt(a.length)];
      a.remove(temp2);
      ans.add(temp2);
      int temp3 = a[rand.nextInt(a.length)];
      ans.add(temp3);
    }
    return ans;
  }
}

关键修改点说明

  1. 状态变量本地化:把所有控制UI的变量移到_LBulbState里,通过setState()触发UI更新。
  2. 动态绑定UI:每个灯光的颜色根据对应的chosen变量切换,比如chosen1为true时显示黄色,否则白色。
  3. 完善点击事件:
    • onTapDown中设置选中状态后调用setState(),立刻刷新UI显示灯光。
    • onTapUp中重置所有chosen状态并调用setState(),让灯光恢复初始样式。
    • 新增onTapCancel处理滑动离开按钮的情况,避免状态残留。
  4. 代码优化:用switch语句替代冗长的if判断,新增resetChosenStates方法统一重置状态,减少重复代码。

内容的提问来源于stack exchange,提问作者מאי כהן

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 14:17:18