Reputation: 10985
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
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
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
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
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