skip to Main Content

I have a flutter application with iterations,and in each iteration there is a countdown button.

When I click on the button the countdown of all the iterations work however my objective is to make only one countdown work.

Here is the countdown function:

  int _countdownTime = 45;
  late Timer _countdownTimer = Timer(Duration(seconds: 0), () {});

  void startCountdownTimer() {
    const oneSec = const Duration(seconds: 1);
    _countdownTimer = new Timer.periodic(
      oneSec,
      (Timer timer) => setState(
        () {
          if (_countdownTime < 1) {
            timer.cancel();
            _countdownTime = 45; // Reset countdown timer to 45 seconds
          } else {
            _countdownTime = _countdownTime - 1;
          }
        },
      ),
    );
  }

  void _handleCountdownTap() {
    if (_countdownTimer == null || !_countdownTimer.isActive) {
      startCountdownTimer();
    }
  }

here is the UI:

for (var breakdown in snapshot.data![index].breakdowns)
  Card(
    margin: EdgeInsets.zero,
    child: Padding(
      padding: EdgeInsets.only(bottom: 8.0, right: 8.0),
      child: Row(
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
          Expanded(
            flex: 1,
            child: Text(
              '${breakdown.order}',
              textAlign: TextAlign.center,
            ),
          ),
          SizedBox(
            height: 30,
            child: GestureDetector(
              onTap: _handleCountdownTap,
              child: Container(
                decoration: BoxDecoration(
                  color: Colors.blue,
                  borderRadius: BorderRadius.circular(8.0),
                ),
                child: Center(
                  child: Text(
                    '$_countdownTime seconds',
                    style: TextStyle(
                      fontSize: 15,
                      color: Colors.white,
                    ),
                  ),
                ),
              ),
            ),
          ),
        ],
      ),
    ),
  ),

My question how to get only one countdown timer to work when clicked instead of all the iterations in the breakdown. Is there another solution or approach to fix this issue

2

Answers


  1. You can create a widget which has timer logic on each item. Something like

    for (var breakdown in snapshot.data![index].breakdowns) {
      BreakdownCard(
        key: ValueKey(breakdown.order),
        label: breakdown.order);
    }
    
    class BreakdownCard extends StatefulWidget {
      final String label;
      const BreakdownCard({super.key, required this.label});
    
      @override
      State<BreakdownCard> createState() => _BreakdownCardState();
    }
    
    class _BreakdownCardState extends State<BreakdownCard> {
      int _countdownTime = 45;
      Timer _countdownTimer = Timer(const Duration(seconds: 0), () {});
    
      void startCountdownTimer() {
        const oneSec = Duration(seconds: 1);
        _countdownTimer = Timer.periodic(
          oneSec,
          (Timer timer) => setState(
            () {
              if (_countdownTime < 1) {
                timer.cancel();
                _countdownTime = 45; // Reset countdown timer to 45 seconds
              } else {
                _countdownTime = _countdownTime - 1;
              }
            },
          ),
        );
      }
    
      void _handleCountdownTap() {
        if (!_countdownTimer.isActive) {
          startCountdownTimer();
        }
      }
    
      @override
      Widget build(BuildContext context) {
        return Card(
          margin: EdgeInsets.zero,
          child: Padding(
            padding: const EdgeInsets.only(bottom: 8.0, right: 8.0),
            child: Row(
              crossAxisAlignment: CrossAxisAlignment.center,
              children: [
                Expanded(
                  flex: 1,
                  child: Text(
                    widget.label,
                    textAlign: TextAlign.center,
                  ),
                ),
                SizedBox(
                  height: 30,
                  child: GestureDetector(
                    onTap: _handleCountdownTap,
                    child: Container(
                      decoration: BoxDecoration(
                        color: Colors.blue,
                        borderRadius: BorderRadius.circular(8.0),
                      ),
                      child: Center(
                        child: Text(
                          '$_countdownTime seconds',
                          style: const TextStyle(
                            fontSize: 15,
                            color: Colors.white,
                          ),
                        ),
                      ),
                    ),
                  ),
                ),
              ],
            ),
          ),
        );
      }
    }
    
    
    Login or Signup to reply.
  2. Something like this?

    import 'package:flutter/material.dart';
    import 'dart:async';
    
    void main() {
      runApp(MyApp());
    }
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'My App',
          home: CountdownExample(),
        );
      }
    }
    
    class CountdownExample extends StatefulWidget {
      @override
      _CountdownExampleState createState() => _CountdownExampleState();
    }
    
    class _CountdownExampleState extends State<CountdownExample> {
      List<int> _countdownTimes = List.filled(3, 45);
      final List<Timer?> _countdownTimers = List.filled(3, null);
    
      void startCountdownTimer(int index) {
        const oneSec = const Duration(seconds: 1);
        _countdownTimers[index] = new Timer.periodic(
          oneSec,
          (Timer timer) => setState(
            () {
              if (_countdownTimes[index] < 1) {
                timer.cancel();
                _countdownTimes[index] = 45; // Reset countdown timer to 45 seconds
              } else {
                _countdownTimes[index] = _countdownTimes[index] - 1;
              }
            },
          ),
        );
      }
    
      void _handleCountdownTap(int index) {
        if (_countdownTimers[index] == null || !_countdownTimers[index]!.isActive) {
          startCountdownTimer(index);
        }
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text('Countdown Example'),
          ),
          body: ListView.builder(
            itemCount: 3,
            itemBuilder: (BuildContext context, int index) {
              return Card(
                margin: EdgeInsets.all(8.0),
                child: Padding(
                  padding: EdgeInsets.all(16.0),
                  child: Row(
                    children: [
                      Expanded(
                        flex: 1,
                        child: Text(
                          'Breakdown ${index + 1}',
                          textAlign: TextAlign.center,
                        ),
                      ),
                      SizedBox(
                        height: 30,
                        child: GestureDetector(
                          onTap: () => _handleCountdownTap(index),
                          child: Container(
                            decoration: BoxDecoration(
                              color: Colors.blue,
                              borderRadius: BorderRadius.circular(8.0),
                            ),
                            child: Center(
                              child: Text(
                                '${_countdownTimes[index]} seconds',
                                style: TextStyle(
                                  fontSize: 15,
                                  color: Colors.white,
                                ),
                              ),
                            ),
                          ),
                        ),
                      ),
                    ],
                  ),
                ),
              );
            },
          ),
        );
      }
    }
    

    enter image description here

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search