Sanzid Sadman
Sanzid Sadman

Reputation: 149

Increase counter faster when long pressed but after a delay in Flutter

I have implemented the following code,

GestureDetector(
                onTap: increaseAge,

                onTapDown: (TapDownDetails details) {
                  timer = Timer.periodic(Duration(milliseconds: 50), (timer) {
                     increaseAge() 
                  });
                },

                onTapUp: (TapUpDetails details) {
                  timer!.cancel();
                },

                onTapCancel: () {
                  timer!.cancel();
                },
),


//here is the increaseAge function
void increaseAge() {
    setState(() {
      age++;
    });
}

What I want is when the user taps, the value increases and updates the UI. But when the user holds the button, the value will increase continuously but after a short delay for better user experience.

Upvotes: 3

Views: 1946

Answers (2)

Peter Koltai
Peter Koltai

Reputation: 9829

Try code below. Currently it cancels if user moves finger during long press above a specific distance. You can fine tune that in onLongPressMoveUpdate, using LongPressMoveUpdateDetails, see here.

import 'package:flutter/material.dart';
import 'dart:async';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      home: const HomePage(),
    );
  }
}

class HomePage extends StatefulWidget {
  const HomePage({Key? key}) : super(key: key);

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  int _age = 1;

  Timer? _timer;
  bool _longPressCanceled = false;

  void _increaseAge() {
    setState(() {
      _age++;
    });
  }

  void _cancelIncrease() {
    if (_timer != null) {
      _timer!.cancel();
    }
    _longPressCanceled = true;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter Demo'),
      ),
      body: Column(
        children: [
          Text(_age.toString()),
          GestureDetector(
            child: Container(
                padding: EdgeInsets.all(20),
                color: Colors.lightBlue,
                child: Center(child: Text('Press or long press here'))),
            onTap: _increaseAge,
            onLongPressEnd: (LongPressEndDetails longPressEndDetails) {
              _cancelIncrease();
            },
            onLongPress: () {
              _longPressCanceled = false;
              Future.delayed(Duration(milliseconds: 300), () {
                if (!_longPressCanceled) {
                  _timer = Timer.periodic(Duration(milliseconds: 150), (timer) {
                    _increaseAge();
                  });
                }
              });
            },
            onLongPressUp: () {
              _cancelIncrease();
            },
            onLongPressMoveUpdate:
                (LongPressMoveUpdateDetails longPressMoveUpdateDetails) {
              if (longPressMoveUpdateDetails.localOffsetFromOrigin.distance >
                  20) {
                _cancelIncrease();
              }
            },
          )
        ],
      ),
    );
  }
}

Upvotes: 3

SUDESH KUMARA
SUDESH KUMARA

Reputation: 1322

Try this one

onLongPressStart: () {
                  //seconds: 2 = short delay
                  Future.delayed(Duration(seconds: 2), () {
                    timer = Timer.periodic(
                        //milliseconds: 500 = increase speed
                        Duration(milliseconds: 500), (Timer t) => increaseAge());
                  });
                }

onLongPressEnd: () {
                  timer!.cancel();
                }

Upvotes: 0

Related Questions