skip to Main Content

I am trying to create simple test, where if user clicks on the right answer, button background changes to green and stays green for 3 seconds.

I implemented set state with timer, but the background change is too instant still, hence timer is not working. Could you please share some thoughts on what could go wrong with that.

Here is my code

          bool _buttonpressed = false;

          void buttonPressed() {
          setState(() {
          if (_buttonpressed == false) {
          _buttonpressed = true;
          }
          else if (_buttonpressed = true) {
          _buttonpressed = false;
          }
          });
          }


                            FilledButton(
                    onPressed: ()  {
                      
                    setState(() {
                      
                    Future.delayed(const Duration(seconds: 3), () {
                    setState(() {
                       _buttonpressed = !_buttonpressed;
                      });
                    });
                    });
                    },
                    style: ButtonStyle(
                    fixedSize: MaterialStateProperty.all(Size(320, 40)),
                    backgroundColor: MaterialStateProperty.resolveWith<Color>(
                    (Set<MaterialState> states) {
                    if (states.contains(MaterialState.pressed)) return Colors.red;
                    return  Color(0XFFE4DBC8);
                  }, 
                ),
              ),
                      

2

Answers


  1. you can define a button like this:

    class DelayedButton extends StatefulWidget {
      final Widget child;
      final VoidCallback onPressed;
      final Duration duration;
      final Color color;
      final Color pressedColor;
    
      const DelayedButton({
        Key? key,
        required this.child,
        required this.onPressed,
        required this.duration,
        required this.color,
        required this.pressedColor,
      }) : super(key: key);
    
      @override
      State<DelayedButton> createState() => DelayedButtonState();
    }
    
    class DelayedButtonState extends State<DelayedButton> {
      bool _buttonpressed = false;
    
      @override
      Widget build(BuildContext context) {
        return FilledButton(
          onPressed: () {
            // if button already pressed do nothing
            if (_buttonpressed) return;
    
            // button has been pressed, update the color now
            setState(() {
              _buttonpressed = true;
            });
    
            // execute 'onPressed' once the button is clicked
            // widget.onPressed();
    
            // update the color again, but delay it first
            Future.delayed(
              widget.duration,
              () => setState(() {
                // execute the 'onPressed' after the 'delayed' is complite
                widget.onPressed();
                _buttonpressed = false;
              }),
            );
          },
          style: FilledButton.styleFrom(
            backgroundColor: _buttonpressed ? widget.color : widget.pressedColor,
          ),
          child: widget.child,
        );
      }
    }
    

    and use it like this:

    DelayedButton(
      onPressed: () {
        /* do some stuff with this button */ print('hello');
      },
      duration: const Duration(seconds: 3),
      color: const Color(0XFFE4DBC8),
      pressedColor: Colors.red,
      child: const Text('button'),
    ),
    
    Login or Signup to reply.
  2. You can consider use Timer to achieve this feature.

    Below is the example code

    import 'dart:async';
    
    import 'package:flutter/material.dart';
    
    class AnswerButton extends StatefulWidget {
      AnswerButton({
        super.key,
        required this.isCorrect,
      });
    
      bool isCorrect;
    
      @override
      State<AnswerButton> createState() => _AnswerButtonState();
    }
    
    class _AnswerButtonState extends State<AnswerButton> {
      late Color emphaColor;
      bool clicked = false;
    
      @override
      void initState() {
        super.initState();
        if (widget.isCorrect) {
          emphaColor = Colors.green;
        } else {
          emphaColor = Colors.red;
        }
      }
    
      void handleClick() {
        setState(() {
          clicked = true;
        });
        Timer(const Duration(seconds: 3), () {
          setState(() {
            clicked = false;
          });
        });
      }
    
      @override
      Widget build(BuildContext context) {
        return ElevatedButton(
          style: ButtonStyle(
            backgroundColor: MaterialStatePropertyAll(
              clicked ? emphaColor : Colors.blue,
            ),
          ),
          onPressed: handleClick,
          child: Text(clicked ? 'Clicked' : 'Button Example'),
        );
      }
    }
    

    In this code, the clicked flag immediately changed after button clicked, and set a Timer that will change the clicked flag 3 sec later

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