0

I'm making a todo app and don't know what is going bad on this. The user can push the button as many time as he want and I want only to function once. How can I do?

onTap: () {
    isComplet = !isComplet;
    if (Todo().isComplet = true) {
        DatabaseService().completTask(todos[index].uid);
    }
    if (Todo().isComplet = false) {
        DatabaseService().uncompletTask(todos[index].uid);
    }
},

I posted before the entire code. If it can help, here's the link to the other question. Thanks!

How can I make that the on ttap button only be pressed one time? - Flutter

greybeard
  • 2,249
  • 8
  • 30
  • 66
Darkka1
  • 3
  • 4

3 Answers3

0

Welcome to Stack Overflow, to execute the function only once, just have a bool variable and set it to false at the start of the widget, possibly in initState() or the builder function of StreamBuilder in case you are building multiple buttons in the same widget

int _buttonPressedOnce = false;

and modify your onTap() function a bit

   onTap: () {
      if (!_buttonPressedOnce) {
        _buttonPressedOnce = true;
        isComplet = !isComplet;
        if (Todo().isComplet = true) {
          DatabaseService().completTask(todos[index].uid);
        }
        if (Todo().isComplet = false) {
          DatabaseService().uncompletTask(todos[index].uid);
        }
      }
    },

Tharun K
  • 1,160
  • 1
  • 7
  • 20
  • It works but when I tried to "complet" other tasks that I created, it doesnt allow me to mark them as completed. Why it can be? – Darkka1 May 13 '21 at 07:18
  • I didn't understand what you mean by 'tried to "complet" other tasks" is your `onTap()` function not even executing once? – Tharun K May 13 '21 at 07:34
  • I have a list of tasks that are created on the todo app, but when I try to mark one as read, the other individual check buttons to press on their respective tasks, are disabled. – Darkka1 May 13 '21 at 07:47
  • ok that's an easy fix, declare this `_buttonPressedOnce` inside your `builder` function under `StreamBuilder` – Tharun K May 13 '21 at 07:55
0

There are two things.

1.) Denounce on Tap to prevent multiple tap:

          bool _isExecuting = false;
          void debounce(Function action) async {
            if (!_isExecuting) {
              _isExecuting = true;
              action();
              await Future.delayed(Duration(milliseconds: 500), () {
                _isExecuting = false;
              });
            }
          }

     
          onTap: (){debounce((){
          // Your code
          })}

2.) Your Logic with tap:

onTap: flag ? () { True case function } : () { False case function },
Dipendra Sharma
  • 2,404
  • 2
  • 18
  • 35
0

This type of functionality isn't the best user experience in my point of view, you can use a loading spinner until the process finishes. But if you want to do that as you said you can do something like below:

(You should use async programming if operations are asynchronous)

First of all, you should define a boolean called tapped or whatever you wanna call with a default value of false,

onTap: (){
    if(tapped) return;
    tapped = true;
    isComplet = !isComplet;
    if (Todo().isComplet = true)
    {DatabaseService().completTask(todos[index].uid);}
    if (Todo().isComplet = false)
    {DatabaseService().uncompletTask(todos[index].uid);}
    tapped = !tapped;
},
M.Taha Basiri
  • 612
  • 1
  • 6
  • 14