Flutter - Как начать следующий обратный отсчет в списке - PullRequest
0 голосов
/ 07 августа 2020

У меня есть список с секундами для таймеров обратного отсчета.

Когда заканчивается первый обратный отсчет в списке, я хочу начать следующий обратный отсчет и т. Д.

Как я могу этого добиться ?

Спасибо!

Мой код до сих пор

import 'dart:async';
 
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:timer_count_down/timer_controller.dart';
 
void main() => runApp(MyApp());
 
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      themeMode: ThemeMode.dark,
      home: Ex(),
    );
  }
}
 
class Ex extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => ExpandableListView();
}
 
class ExpandableListView extends State<Ex> {
  final CountdownController controller = CountdownController();
  List<int> list = [3, 4, 5, 6];
  Timer _timer;
  int counter = 3;
 
  void _startTimer(seconds) {
 
    if (_timer != null) {
      _timer.cancel();
    }
 
    _timer = Timer.periodic(Duration(hours:0, minutes: 0, seconds: seconds), (timer) {
      setState(() {
        if (counter > 0) {
          counter--;
        } else {
          _timer.cancel();
        }
      });
    });
  }
 
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      body: Container(
        height: 500,
        width: 200,
        child: Column(
          children: [
            Container(
              height: 200,
              width: 200,
              child: ListView.builder(
                itemCount: list.length,
                itemBuilder: (context, index) {
                  return Text(list[index].toString());
                },
              ),
            ),
            RaisedButton(
              onPressed: () {
                setState(() {
                  _startTimer(list[0]);
                });
              },
            ),
          ],
        ),
      ),
    );
  }
}

Ответы [ 2 ]

1 голос
/ 07 августа 2020

Это можно сделать примерно так.

class _MyWidgetState extends State<MyWidget> {
  List<int> list = [3, 4, 5, 6];
  Timer _timer;
  int currentIndex = 0;           //<-- to track which timer is running at the moment

  void _startTimer() {
    _timer = Timer.periodic(Duration(seconds: 1), (_) {
      setState(() {
        if (list[currentIndex] > 0) {
          list[currentIndex]--;
        } else {
          if (currentIndex != (list.length - 1)) {
            currentIndex++;
            list[currentIndex]--;
          }
        }
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        children: [
          Expanded(
            child: ListView.builder(
              itemCount: list.length,
              itemBuilder: (context, index) {
                return Text('${list[index]}');
              },
            ),
          ),
          RaisedButton(
            child: Text('Start'),
            onPressed: _startTimer,
          ),
        ],
      ),
    );
  }

  @override
  void dispose() {
    _timer.cancel();
    super.dispose();
  }
}

Ссылка на демонстрацию на дартпаде - https://dartpad.dev/ca29e0b73e1d919d941e113174b747cf

Чтобы удалить таймер после завершения, вы можете сделать вот так.

itemBuilder: (context, index) {
                if(list[index] == 0){
                  return const SizedBox();
                }
                else{
                  return Text('${list[index]}');
                }
              }
1 голос
/ 07 августа 2020

Я добавил список логических значений для управления виджетом CountDown независимо от того, приостановлен он или нет. Вот корректировка вашего кода ниже.

Основной виджет для создания элемента для ListView - это

Widget buildItem(int index) {
return !isPauseList[index]
    ? Countdown(
        seconds: list[index],
        build: (BuildContext context, double time) => Text(time.toString()),
        interval: Duration(milliseconds: 100),
        controller: controller,
        onFinished: () {
          if (index < isPauseList.length) {
            setState(() {
              isPauseList[index + 1] = false;
            });
          }
        },
      )
    : Text(list[index].toString());

}

И полная корректировка вашего кода приведена ниже.

import 'dart:async';

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:timer_count_down/timer_controller.dart';
import 'package:timer_count_down/timer_count_down.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      themeMode: ThemeMode.dark,
      home: Ex(),
    );
  }
}

class Ex extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => ExpandableListView();
}

class ExpandableListView extends State<Ex> {
  final CountdownController controller = CountdownController();
  List<int> list = [3, 4, 5, 6];
  List<bool> isPauseList = [true, true, true, true];
  Timer _timer;
  int counter = 3;

  void _startTimer() {
    setState(() {
      this.isPauseList[0] = false;
    });
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      body: Container(
        height: 500,
        width: 200,
        child: Column(
          children: [
            Container(
              height: 200,
              width: 200,
              child: ListView.builder(
                itemCount: list.length,
                itemBuilder: (context, index) {
//                  return Text(list[index].toString());
                  return buildItem(index);
                },
              ),
            ),
            RaisedButton(
              onPressed: () {
                setState(() {
                  _startTimer();
                });
              },
            ),
          ],
        ),
      ),
    );
  }

  Widget buildItem(int index) {
    return !isPauseList[index]
        ? Countdown(
            seconds: list[index],
            build: (BuildContext context, double time) => Text(time.toString()),
            interval: Duration(milliseconds: 100),
            controller: controller,
            onFinished: () {
              if (index < isPauseList.length) {
                setState(() {
                  isPauseList[index + 1] = false;
                });
              }
            },
          )
        : Text(list[index].toString());
  }
}
...