how to implement button with timeout in flutter

434

Solution 1

You can easily achieve it with a CustomPainter widget. Check the source code below and tweak it to your needs.

enter image description here


import 'dart:async';

import 'package:flutter/material.dart';

class MyProgressButton extends StatefulWidget {
  @override
  _MyProgressButtonState createState() => _MyProgressButtonState();
}

class _MyProgressButtonState extends State<MyProgressButton> {
  Timer _timer;
  int _progress = 0;
  int _totalActionTimeInSeconds = 3;

  void _initCounter() {
    _timer?.cancel();
    _progress = 0;
    _timer = Timer.periodic(const Duration(milliseconds: 50), (_) {
      setState(() => _progress += 50);

      if (Duration(milliseconds: _progress).inSeconds >= _totalActionTimeInSeconds) {
        _timer.cancel();
        // Do something
      }
    });
  }

  void _stopCounter() {
    _timer?.cancel();
    setState(() => _progress = 0);
  }

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTapDown: (_) => _initCounter(),
      onTapUp: (_) => _stopCounter(),
      child: CustomPaint(
        painter: _MyCustomButtonPainter((_progress / 1000) / _totalActionTimeInSeconds),
        child: Container(
          alignment: Alignment.center,
          width: 500.0,
          height: 200.0,
          child: Text('Press me'),
        ),
      ),
    );
  }
}

class _MyCustomButtonPainter extends CustomPainter {
  const _MyCustomButtonPainter(this.progress);

  final double progress;

  @override
  void paint(Canvas canvas, Size size) {
    final Paint paint = Paint()..color = Colors.grey;
    final double buttonWidth = size.width;
    final double buttonHeight = size.height;

    canvas.drawRRect(
      RRect.fromRectAndRadius(
        Rect.fromLTRB(0.0, 0.0, buttonWidth, buttonHeight),
        Radius.circular(5.0),
      ),
      paint,
    );

    paint.color = Colors.green;

    canvas.drawRRect(
      RRect.fromRectAndRadius(
        Rect.fromLTRB(0.0, 0.0, progress * buttonWidth, buttonHeight),
        Radius.circular(5.0),
      ),
      paint,
    );
  }

  @override
  bool shouldRepaint(_MyCustomButtonPainter oldDelegate) => this.progress != oldDelegate.progress;
}

Solution 2

Try this:

class Button extends StatefulWidget {
  @override
  _ButtonState createState() => _ButtonState();
}

class _ButtonState extends State<Button> {
  double progress;
  Timer timer;

  @override
  void initState() {
    timer = Timer.periodic(Duration(milliseconds: 50), (timer) {
      if (progress <= 0) return timer.cancel();
      setState(() {
        progress -= 0.0025;
      });
    });
    progress = 1;
    super.initState();
  }

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

  @override
  Widget build(BuildContext context) {
    return ClipRRect(
      borderRadius: BorderRadius.circular(5),
      child: Container(
        height: 70,
        width: 200,
        child: Stack(
          alignment: Alignment.center,
          children: [
            SizedBox.expand(
              child: LinearProgressIndicator(
                value: progress,
                backgroundColor: Colors.grey,
                valueColor: AlwaysStoppedAnimation(Colors.green),
              ),
            ),
            Text(
              'Button',
              style: TextStyle(color: Colors.white),
            ),
          ],
        ),
      ),
    );
  }
}
Share:
434
Akbar Pulatov
Author by

Akbar Pulatov

Engineer of Embedded Systems

Updated on December 27, 2022

Comments

  • Akbar Pulatov
    Akbar Pulatov over 1 year

    User can tap button until the end of timer. I don't know how to start the layout. Does flutter sdk have any built in (or similar to be implemented) widgets for this case.

    enter image description here