79

In Android, we can call setOnFocusChangeListener(), do something in onFocusChanged() method, but flutter does not provider onFocus() interface like onTap() in GestureDetector or onKey() in RawKeyboardListener.

I have read flutter api about focus, https://docs.flutter.io/flutter/widgets/FocusManager-class.html but I can't find a way to realize my request, anyone who can give me a hand?

Albert221
  • 4,181
  • 3
  • 27
  • 36
coder.john
  • 975
  • 1
  • 10
  • 11
  • 1
    I agree - its hard to understand the intent from the documentation. Example would be great as well. – Ride Sun Jan 31 '18 at 22:45
  • [Haider Abbas](https://stackoverflow.com/users/4729459) posted an [Answer](https://stackoverflow.com/a/67089822) saying "You may use MouseRegion() events like [https://api.flutter.dev/flutter/widgets/MouseRegion-class.html](https://api.flutter.dev/flutter/widgets/MouseRegion-class.html) onEnter, onExit" – Scratte Apr 19 '21 at 07:44

3 Answers3

127

In addtion you can use Focus widget.

Focus(
  child: TextFormField(...),
  onFocusChange: (hasFocus) {
    if(hasFocus) {
      // do stuff
    }
  },
)
GoodSp33d
  • 6,202
  • 4
  • 32
  • 67
BambinoUA
  • 4,295
  • 3
  • 28
  • 39
91

Using FocusNode

Here is a fully correct answer. addListener shall be in initState(), not build(), because that would result in adding a listener every time a widget is built and you most likely don't want that.

import 'package:flutter/material.dart';

class SomeWidget extends StatefulWidget {
  @override
  _SomeWidgetState createState() => _SomeWidgetState();
}

class _SomeWidgetState extends State<SomeWidget> {
  final _focusNode = FocusNode();
    
  @override
  void initState() {
    super.initState();
    _focusNode.addListener(() {
      print("Has focus: ${_focusNode.hasFocus}");
    });
  }
    
  @override
  Widget build(BuildContext context) {
    return TextField(focusNode: _focusNode);
  }
    
  @override
  void dispose() {
    _focusNode.dispose();
    super.dispose();
  }
}

Using flutter_hooks package

If you're by any chance using the flutter_hooks package, there is a dedicated useFocusNode hook.

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

class SomeWidget extends HookWidget {
  @override
  Widget build(BuildContext context) {
    final focusNode = useFocusNode();
    useEffect(() {
      focusNode.addListener(() {
        print("Has focus: ${focusNode.hasFocus}");
      });
      return; // You need this return if you have missing_return lint
    }, [focusNode]);

    return TextField(focusNode: focusNode);
  }
}
Albert221
  • 4,181
  • 3
  • 27
  • 36
  • Thanks @Albert221, I was going through this problem of receiving multiple calls, now I managed to solve. – Luan Martins Gepfrie Jul 26 '19 at 12:25
  • 10
    *Note:* a node focus listener is called twice: when it acquires focus and when it loses the focus. Inside the callback `node.hasFocus` would be `true` or `false` respectively – Kirill Karmazin Dec 09 '19 at 12:09
36

I suppose you are looking for FocusNode class. Use addListener method to add a listener function that listens to focus change.

Example
declare and define FocusNode

 var focusNode = FocusNode();
  @override
  void initState() {
    focusNode.addListener(() {
      print(focusNode.hasFocus);
    });
    super.initState();
  }

Use focus node in textfield

TextField(
            focusNode: focusNode,
          ),

Output

when textfield is focus you will get true else false

codingwithtashi
  • 1,431
  • 1
  • 16
  • 25
Hemanth Raj
  • 28,663
  • 8
  • 86
  • 76