Flutter: How to change focus to another widget when a certain key is pressed on physical keyboard

1,360

I have achieved your use case by just modified your code snippets. Please check the below code snippets. FocusScope.of(context).nextFocus() is used to move the focus to the next. If you want to move a focus to a specific widget. you just call that focusNode.requestFocus().


class FocusDemo extends StatefulWidget {
  @override
  _FocusDemoState createState() => _FocusDemoState();
}

class _FocusDemoState extends State<FocusDemo> {
  late FocusNode _txtNode;

  @override
  void initState() {
    super.initState();
    _txtNode = FocusNode();
  }

  @override
  void dispose() {
    _txtNode.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: Focus(
          focusNode: _txtNode,
          onKey: (focusNode, event) {
            if (event.runtimeType == RawKeyUpEvent &&
                event.logicalKey == LogicalKeyboardKey.enter) {
              focusNode.nextFocus();
              return KeyEventResult.handled;
            }
            return KeyEventResult.ignored;
          },
          child: Container(
            height: 400,
            width: 500,
            color: Colors.grey[350],
            child: Column(
              children: [
                TextField(),
                TextField(),
                TextField(),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

Share:
1,360
West
Author by

West

Updated on December 30, 2022

Comments

  • West
    West over 1 year

    I'm developing a desktop app on Windows and am trying to move focus to a Textfield when the ENTER key is pressed on another textfield. I'm able to detect the key has been pressed using RawKeyboardListener but focus isnt changed to the new field. How can I get this working?

    import 'package:flutter/material.dart';
    
    void main() {
      runApp(MyApp());
    }
    
    class MyApp extends StatefulWidget {
      @override
      _MyAppState createState() => _MyAppState();
    }
    
    class _MyAppState extends State<MyApp> {
      late FocusNode _txtNode;
    
      @override
      void initState() {
        super.initState();
        _txtNode = FocusNode();
      }
    
      @override
      void dispose() {
        _txtNode.dispose();
    
        super.dispose();
      }
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          home: Scaffold(
            body: SafeArea(
              child: Stack(
                children: [
                  Container(
                  height: 400,
                  width: 500,
                  color: Colors.grey[350],
                  child: Column(
                    children: [
                      Container(
                          height: 100,
                          child: RawKeyboardListener(
                            focusNode: FocusNode(),
                              onKey: (event){
                              if (event.toString().contains('RawKeyDownEvent') && event.toString().contains('Enter')) {
                                print("pressed ENTER");
                                _txtNode.requestFocus();
                              }
                              },
                              child: TextField(readOnly: true,))
                      ),
                      TextField(
                      ),
                      TextField(
                        focusNode: _txtNode,
                      ),
                    ],
                  ),
                ),
              ]
              ),
            ),
          ),
        );
      }
    }
    
  • West
    West almost 3 years
    I've retested and it doesnt seem to be working. Focus is not being set
  • Ashok Kuvaraja
    Ashok Kuvaraja almost 3 years
    Okay brother, I will check and revert back.
  • Ashok Kuvaraja
    Ashok Kuvaraja almost 3 years
    @West, Can you please check the current code snippets?
  • West
    West almost 3 years
    Screen doesnt render no more I got an error No MediaQuery widget ancestor found.The relevant error-causing widget was: FocusDemo file:///C:/Users/Public/Android/Projects/tests/lib/main.dart‌​:5:10 Are you testing the code before posting and does it work on your end?
  • Ashok Kuvaraja
    Ashok Kuvaraja almost 3 years
    Yes I ensured. Please wrap MaterialApp widget to the parent of Scaffold widget and check?
  • West
    West almost 3 years
    Sure that makes it render again. But seems now none of the TextFields can be typed into
  • West
    West almost 3 years
    Thanks I've edited your answer so that it allows the TextFields to be edited. I'll accept it now:)
  • West
    West almost 3 years
    I've heard about issues with checking event.runtimeType in production so I instead use if (event.toString().contains('RawKeyDownEvent') && event.toString().contains('Enter')) {}