首页 > 解决方案 > 国际象棋应用程序的 Flutter 倒数计时器(卡在逻辑中)

问题描述

所以从过去的几天开始,我一直在试图绕过这个逻辑循环,并尝试了我能做的一切,最后决定在这里发布(因此在这里首次亮相)。我被卡住了,感谢所有帮助。谢谢 !

逻辑:在应用程序中有 2 个container显示白色和黑色的时间,从给定的五个选项中选择 -> 5,10,15,30,60,然后更新在这些容器中显示的时间,使用了一个provider包这和其他一切。

现在我还添加了一个Raised button名为“开关”,按下它应该:

  1. 开始是白人的倒计时
  2. 然后如果再次按下应该停止白方的计时器,然后启动黑方的倒计时
  3. 然后如果再次按下应该停止黑色的计时器,然后启动白色的计时器。
  4. 并重复直到计时器用完并且两人中的一人被宣布为获胜者。

问题: 所以到目前为止我编码的内容,当按下“开关”时,它会启动白色的计时器,如果再次按下会停止白色的计时器,但它不会启动黑色的计时器。我知道这是因为我构建if() 条件的方式,也因为我不知道如何从外部停止计时器。我所做的是对每个白色和黑色使用 - bool checkTimerWcheckTimerB,我在if()条件中检查以取消计时器是基于它的。

代码:

提供者 -

import 'dart:async';

import 'package:flutter/foundation.dart';

class SettingsProvider extends ChangeNotifier {
  int valueW = 0;
  int valueB = 0;

// * with these booleans we will stop the timer.
  bool checkTimerW = true;
  bool checkTimerB = true;


  String timeToDisplayW = ""; // for white
  String timeToDisplayB = ""; // for black

  bool switchT = false;

   // this is called in the settings Modal Bottom Sheet
  void changeValue(int valW, int valB) {
    
   //? Changing the value in seconds
    valueW = valW * 60;
    valueB = valB * 60;

    print(valueW);

    timeToDisplayW = valueW.toString();
    timeToDisplayB = valueB.toString();
    notifyListeners();
  }

  void reset() {
    started = true;
    stopped = true;
    checkTimerW = false;
    checkTimerB = false;
    notifyListeners();
  }

  void toggleSwitch() {
    if (switchT == false) {
      switchT = true;
      print('true');
    } else if (switchT == true) {
      switchT = false;
      print('false');
    }
  }

  void switchTimer() {
    if (switchT == false) {

      // Starts white's timer

      Timer.periodic(
        Duration(seconds: 1),
        (Timer t) {
          if (valueW <= 1 || checkTimerW == false) {
            t.cancel();
            checkTimerW = true;

            // TODO : Black Won

            notifyListeners();
          } else {
            valueW = valueW - 1;
            notifyListeners();
          }

          timeToDisplayW = valueW.toString();
          notifyListeners();
        },
      );

      // stops black's timer

      checkTimerB = false;
      toggleSwitch();
      notifyListeners();

    } else {

      // Starts black's timer

      Timer.periodic(
        Duration(seconds: 1),
        (Timer t) {
          if (valueB <= 1 || checkTimerB == false) {
            t.cancel();
            checkTimerB = true;

            // TODO : White won

            notifyListeners();
          } else {
            valueB = valueB - 1;
            notifyListeners();
          }

          timeToDisplayB = valueB.toString();
          notifyListeners();
        },
      );

      // stops white's timer
      checkTimerW = false;
      toggleSwitch();
      notifyListeners();
      
  }
 }
}

Main.dart -

import 'dart:math';


import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:provider/provider.dart';

import 'controller/countdown_controller.dart';
import 'widgets/blackButton.dart';
import 'widgets/bottom_sheet_design.dart';
import 'widgets/whiteButton.dart';
import 'providers/settings.dart';


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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    SystemChrome.setPreferredOrientations([
      DeviceOrientation.portraitUp,
      DeviceOrientation.portraitDown,
    ]);
    return ChangeNotifierProvider(
      create: (ctx) => SettingsProvider(),
      child: MaterialApp(
        title: 'Flutter Demo',
        theme: ThemeData(
          primarySwatch: Colors.amber,
          visualDensity: VisualDensity.adaptivePlatformDensity,
        ),
        home: MyHomePage(),
      ),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
      
  void settings(BuildContext ctx) {
    showModalBottomSheet(
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.only(
          topLeft: Radius.circular(10),
          topRight: Radius.circular(10),
        ),
      ),
      context: ctx,
      builder: (_) => BottomSheetDesign(),
    );
  }

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Scaffold(
        backgroundColor: Colors.grey[350],
        body: Row(
          mainAxisSize: MainAxisSize.min,
          children: <Widget>[
            Expanded(
              flex: 1,
              child: Transform.rotate(
                angle: pi / 1,
                child: GestureDetector(
                  onTap: () {
                    Provider.of<SettingsProvider>(context, listen: false)
                        .switchTimer();
                  },
                  child: Container(
                    width: 80.0,
                    height: 500,
                    child: Center(
                      child: Transform.rotate(
                        angle: pi / 2,
                        child: Text('Switch',
                            style: Theme.of(context).textTheme.bodyText2),
                      ),
                    ),
                    decoration: BoxDecoration(
                      color: Colors.blueGrey,
                    ),
                  ),
                ),
              ),
            ),
            VerticalDivider(),
            Expanded(
              flex: 4,
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  Row(
                    children: <Widget>[

                      // container that displays black's timer
                      BlackButton(),

                      Expanded(
                        child: Transform.rotate(
                          angle: pi / 2,
                          child: RaisedButton(
                            onPressed: () {
                              settings(context);
                            },
                            color: Colors.blue[300],
                            child: Text('Settings'),
                          ),
                        ),
                      ),
                    ],
                  ),
                  SizedBox(
                    height: 20,
                  ),
                  Row(
                    children: <Widget>[

                      // container that displays white's timer
                      WhiteButton(),

                      Expanded(
                        child: Transform.rotate(
                          angle: pi / 2,
                          child: RaisedButton(
                            onPressed: () {
                              Provider.of<SettingsProvider>(context, listen: false).reset();
                            },
                            color: Colors.red[600],
                            child: Text('Reset'),
                          ),
                        ),
                      ),
                    ],
                  ),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }
}

标签: flutterdarttimercountdowntimerflutter-timer

解决方案


我过去已经对此进行了编码。它可能会帮助你。

class DoubleTimer extends StatefulWidget {
  @override
  _DoubleTimerState createState() => _DoubleTimerState();
}

class _DoubleTimerState extends State<DoubleTimer> {
  int timeToGoA = 50000;
  int timeToGoB = 50000;

  int state = 0; //0: waiting, 1: counting A, 2: counting B

  DateTime timeStamp;

  _DoubleTimerState() {
    print("init");
  }

  @override
  Widget build(BuildContext context) {
    print(
        "${DateTime.now().compareTo(DateTime.now().add(Duration(seconds: 1)))}");
    return Row(
      children: <Widget>[
        if (state == 1)
          ToTime(timeStamp.add(Duration(milliseconds: timeToGoA))),
        FlatButton(
          onPressed: () {
            setState(() {
              switch (state) {
                case 0:
                  state = 1;
                  timeStamp = DateTime.now();
                  print("Running A");
                  break;
                case 1:
                  state = -1;
                  timeToGoA -=
                      DateTime.now().difference(timeStamp).inMilliseconds;
                  timeStamp = DateTime.now();
                  print("A: $timeToGoA\nRunning B");
                  break;
                case -1:
                  state = 1;
                  timeToGoB -=
                      DateTime.now().difference(timeStamp).inMilliseconds;
                  timeStamp = DateTime.now();
                  print("B: $timeToGoB\nRunning A");
                  break;
              }
            });
          },
          child: Text("switch"),
        ),
        if (state == -1)
          ToTime(timeStamp.add(Duration(milliseconds: timeToGoB))),
      ],
    );
  }
}

class ToTime extends StatelessWidget {
  final DateTime timeStamp;

  const ToTime(this.timeStamp, {Key key}) : super(key: key);

  static final Map<String, int> _times = <String, int>{
    'y': -const Duration(days: 365).inMilliseconds,
    'm': -const Duration(days: 30).inMilliseconds,
    'w': -const Duration(days: 7).inMilliseconds,
    'd': -const Duration(days: 1).inMilliseconds,
    'h': -const Duration(hours: 1).inMilliseconds,
    '\'': -const Duration(minutes: 1).inMilliseconds,
    '"': -const Duration(seconds: 1).inMilliseconds,
    "ms": -1,
  };

  Stream<String> get relativeStream async* {
    while (true) {
      int duration = DateTime.now().difference(timeStamp).inMilliseconds;
      String res = '';
      int level = 0;
      int levelSize;
      for (MapEntry<String, int> time in _times.entries) {
        int timeDelta = (duration / time.value).floor();
        if (timeDelta > 0) {
          levelSize = time.value;
          res += '$timeDelta${time.key} ';
          duration -= time.value * timeDelta;
          level++;
        }
        if (level == 2) {
          break;
        }
      }
      levelSize ??= _times.values.reduce(min);
      if (level > 0 && level < 2) {
        List<int> _tempList =
            _times.values.where((element) => (element < levelSize)).toList();

        if (_tempList.isNotEmpty) levelSize = _tempList.reduce(max);
      }
      if (res.isEmpty) {
        yield 'now';
      } else {
        res.substring(0, res.length - 2);
        yield res;
      }
//      print('levelsize $levelSize sleep ${levelSize - duration}ms');
      await Future.delayed(Duration(milliseconds: levelSize - duration));
    }
  }

  @override
  Widget build(BuildContext context) {
    return StreamBuilder<String>(
        stream: relativeStream,
        builder: (context, snapshot) {
          return Text(snapshot.data ?? '??');
        });
  }
}

推荐阅读