【问题标题】:Flutter: Continuously running stopwatch when switching screensFlutter:切换屏幕时连续运行秒表
【发布时间】:2019-08-20 08:13:47
【问题描述】:

我有一个stopwatch 小部件,它是从我的一个屏幕上的Detailed Activity 页面调用的,该页面在页面加载时启动。我怎样才能让它在后台持续运行,以便当我从 Detailed Activity 导航到 Home 页面时,我可以显示相同的秒表时间?

此时,Home 页面显示上次保存的时间(到变量中)。相反,我希望它每秒继续递增,反之亦然,在两个屏幕之间切换。我尝试在Home 页面中添加startWatch()initState() 方法,但在导航到Detailed Activity 页面时不知道如何传递秒表值

为了更清楚地说明这一点,我的想法是在 Detailed Activity 页面上,例如00:15:00 -> 将其传递到Home 页面并调用 initState() 以再次自动启动计时器。这行得通吗?

Timer.dart

class NewStopWatch extends StatefulWidget {

  @override
  _NewStopWatchState createState() => new _NewStopWatchState();
}

class _NewStopWatchState extends State<NewStopWatch> {

  static _NewStopWatchState stopwatch;
  Stopwatch watch = new Stopwatch();
  Timer timer;
  bool startStop = true;
  static String elapsedTime = '';
  String duration;

  updateTime(Timer timer) {
    if (watch.isRunning) {
      setState(() {
        elapsedTime = transformMilliSeconds(watch.elapsedMilliseconds);
        User.getCurrentUser().getCurrentActivity().setElapsedTime(elapsedTime);
      });
    }
  }
@override
  Widget build(BuildContext context) {

    return new Container(
            padding: EdgeInsets.all(20.0),
            child: new Column(
              children: <Widget>[
                new Text(elapsedTime, style: new TextStyle(fontSize: 25.0)),
                SizedBox(height: 20.0),
                new Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: <Widget>[
                FloatingActionButton(
                  heroTag: "btn1",
                  backgroundColor: Colors.red,
                  onPressed: () => startOrStop(),
                  child: Icon(Icons.pause)),
                SizedBox(width: 20.0),
                FloatingActionButton(
                  heroTag: "btn2",
                  backgroundColor: Colors.green,
                  onPressed: () => completeActivity(),
                  child: Icon(Icons.check)),
                  ],
                )
              ],
            ));
  }

  void initState() {
    super.initState();
    WidgetsBinding.instance
        .addPostFrameCallback((_) => startWatch());
  }

  startOrStop() {
    if(startStop) {
      startWatch();
    } else {
      stopWatch();
    }
  }

  startWatch() {
    setState(() {
      startStop = false;
      watch.start();
      timer = Timer.periodic(Duration(milliseconds: 100), updateTime);
    });
  }

  stopWatch() {
    setState(() {
      startStop = true;
      watch.stop();
      setTime();
    });
  }

  resetWatch() {
    watch.reset();
    setTime();
  }

  setTime() {
    var timeSoFar = watch.elapsedMilliseconds;
    setState(() {
      elapsedTime = transformMilliSeconds(timeSoFar);
    });
  }

  completeActivity() { //do I call activity.stopActivity()?
    return showDialog(
          context: context,
          builder: (context) => new AlertDialog(
                title: new Text('Complete Activity?',
                    style: new TextStyle(color: Colors.black, fontSize: 20.0)),
                actions: <Widget>[
                  new FlatButton(
                    onPressed: () {
                      duration = elapsedTime;
                      print("Current activitiy: ${User.getCurrentUser().getCurrentActivity()}");
                      // User.getCurrentUser().completeActivity();
                      User.getCurrentUser().addPastActivity(User.getCurrentUser().getCurrentActivity());
                      User.getCurrentUser().getCurrentActivity().setStatus(ActivityStatus.completed);
                      User.getCurrentUser().setCurrentActivity(null);
                      Navigator.push(context, MaterialPageRoute(builder: (context) => FrontPage()));
                      // Navigator.popUntil(context, ModalRoute.withName("/"),);
                    },
                    child:
                        new Text('Yes', style: new TextStyle(fontSize: 18.0)),
                  ),
                  new FlatButton(
                    onPressed: () => Navigator.pop(context), // this line dismisses the dialog
                    child: new Text('No', style: new TextStyle(fontSize: 18.0)),
                  )
                ],
              ),
        ) ??
        false;
    }

  transformMilliSeconds(int milliseconds) {
    int hundreds = (milliseconds / 10).truncate();
    int seconds = (hundreds / 100).truncate();
    int minutes = (seconds / 60).truncate();
    int hours = (minutes / 60).truncate();

    String hoursStr = (hours % 60).toString().padLeft(2, '0');
    String minutesStr = (minutes % 60).toString().padLeft(2, '0');
    String secondsStr = (seconds % 60).toString().padLeft(2, '0');

    return "$hoursStr:$minutesStr:$secondsStr";
  }

   static String getElapsedTime() {
    return elapsedTime;
  }
}

【问题讨论】:

  • 似乎您应该查看 bloc 模式和 bloc 提供程序。您可以创建一个处理 Timer 的 bloc 类,然后将值流式传输到使用秒表的所有屏幕。一个很好的介绍可以在这里找到:flutterdevs.com/blog/bloc-pattern-in-flutter-part-1

标签: flutter dart timer widget stopwatch


【解决方案1】:

由于您发布了很多代码,但它缺少实际显示 NewStopWatch 的部分,但我希望此解决方案有所帮助:

在 NewStopWath 类的 init 方法中将秒表和计时器作为参数传递,并让它们从您的主页传递——您希望它们显示的页面......我想它是 FrontPage。

像这样:

class FrontPage extends StatelessWidget {
    Stopwatch watch = Stopwatch();
    Timer timer = Timer.periodic(Duration(milliseconds: 100), updateTime);
//... code

//.. somewhere a NewStopWatch is created 
           return NewStopWatch(watch, timer);
    }
//... code


class NewStopWatch extends StatefulWidget {

  Stopwatch watch;     
  Timer timer;

  NewStopWatch(this.watch, this.timer);

  @override
  _NewStopWatchState createState() => new _NewStopWatchState();
}


class _NewStopWatchState extends State<NewStopWatch> {

  static _NewStopWatchState stopwatch;
  bool startStop = true;
  static String elapsedTime = '';
  String duration;

  Stopwatch get watch => widget.watch;
  Timer get timer => widget.timer;

  void initState() {
    super.initState();

    WidgetsBinding.instance
        .addPostFrameCallback((_) => startWatch());
  }

一定要检查是否应该删除 timer = Timer.periodic(Duration(milliseconds: 100), updateTime);从 startWatch() 也许您不需要将其作为参数传递

【讨论】:

    猜你喜欢
    • 2019-12-15
    • 1970-01-01
    • 1970-01-01
    • 2020-08-22
    • 1970-01-01
    • 2015-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多