Vicky Salunkhe
Vicky Salunkhe

Reputation: 10985

How to detect user has stopped typing in TextField?

I am using a TextField under which onChanged function

I am calling my code but the issue right now is the code gets execute everytime a new word is either entered or deleted.

what I am looking for is how to recognize when a user has stopped typing.

means adding some delay or something like that.

I have tried adding delay also using Future.delayed function but that function also gets executed n number of times.

TextField(
   controller: textController,
   onChanged: (val) {
            if (textController.text.length > 3) {
              Future.delayed(Duration(milliseconds: 450), () {
                 //code here
              });
            }
            setState(() {});
          },
 )

Upvotes: 11

Views: 8177

Answers (4)

Mohammad Khan Awan
Mohammad Khan Awan

Reputation: 504

I know this is pretty late. In my case I needed to check the availability of an email during the sign up process and needed to show the relevant message to user when the user stopped typing the email in the textfield. You need to create a timer and reset it every time the user types something inside the textfield. Here's the code:

Timer? _checkTypingTimer;

startTimer() {
    _checkTypingTimer = Timer(const Duration(milliseconds: 600), () {//set your desired duration
      //perform your logic here
      //i was calling the method here which checks if the email is available or not
    });
  }

resetTimer() {
    _checkTypingTimer?.cancel();
    startTimer();
  }

Now call this resetTimer method inside the onChanged method of your textfield. And don't forget to import dart:async

Note: The answer given above with the medium link, the "debouncer one", may needlessly invoke your code several times

Upvotes: 1

Hamid Waezi
Hamid Waezi

Reputation: 897

I find something so lighter in this link

it define this class

class Debouncer {
  final int milliseconds;

  Timer? _timer;

  Debouncer({this.milliseconds=500});

  run(VoidCallback action) {
    if (null != _timer) {
      _timer!.cancel();
    }
    _timer = Timer(Duration(milliseconds: milliseconds), action);
  }
}

this sample will help you more

TextField(
     decoration: new InputDecoration(hintText: 'Search'),
     onChanged: (string) {
       _debouncer.run(() {
       print(string);
       //perform search here
       });
     },
   ),

Upvotes: 3

RHS.Dev
RHS.Dev

Reputation: 452

In my case I also required flutter async.

//pubspec.yaml
stream_transform: ^2.0.0

import 'dart:async';
import 'package:stream_transform/stream_transform.dart';

StreamController<String> streamController = StreamController();

// In init function
streamController.stream
    .debounce(Duration(seconds: 1))
    .listen((s) => { 
       // your code 
     });

// In build function
TextField(
   style: TextStyle(fontSize: 16),
   controller: messageController,
   onChanged: (val) {
     myMetaRef.child("isTyping").set(true);
     streamController.add(val);
     },
   )

Upvotes: 1

Vicky Salunkhe
Vicky Salunkhe

Reputation: 10985

Thanks to @pskink

I was able to achieve the functionality I was looking for.

import stream_transform package in your pubspec.yaml

stream_transform: ^0.0.19

import 'package:stream_transform/stream_transform.dart';

StreamController<String> streamController = StreamController();

@override
void initState() {
  streamController.stream
    .transform(debounce(Duration(milliseconds: 400)))
    .listen((s) => _validateValues());

  super.initState();
}

//function I am using to perform some logic
_validateValues() {
  if (textController.text.length > 3) {
     // code here
  }else{
     // some other code here
  }
}

TextField code

TextField(
   controller: textController,
   onChanged: (val) {
        streamController.add(val);
     },
)

Upvotes: 2

Related Questions