grepLines
grepLines

Reputation: 2558

How to listen to keyboard on screen Flutter?

I am building a mobile app, I want to remove a widget when the keyboard appears on the screen, i.e when the input text field is on focus.

I have tried to use RawKeyboardListener but that doesn't seem to work, my code is as below:

new Container(
  child: new RawKeyboardListener(
    focusNode: new FocusNode(),
    onKey: (input) => debugPrint("*****KEY PRESSED"),
    child: new TextField(
      controller: new TextEditingController(),
    ),
  ),
);

Upvotes: 24

Views: 45234

Answers (8)

INDIAN GAMER
INDIAN GAMER

Reputation: 178

Hi I did this without any package,Here override didchange method and listen keyboard ,if its visible or not..

class _LoginScreenState extends State<LoginScreen> with WidgetsBindingObserver {
 
  bool hideImage = false;

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(this);
  }

  @override
  void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    super.dispose();
  }


  @override
  void didChangeMetrics() {
    final value = WidgetsBinding
        .instance.platformDispatcher.views.first.viewInsets.bottom;
    if (value != 0.0) {
      // WHEN KEYBOARD POP UP
      setState(() {
        hideImage = true;
      });
    } else {
      setState(() {
        hideImage = false;
      });
    }
  }

Upvotes: 2

مصطفى
مصطفى

Reputation: 915

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

class KeyboardHookWidget extends HookWidget {
  const KeyboardHookWidget({super.key});

  @override
  Widget build(BuildContext context) {
    late StreamSubscription<bool> keyboardSubscription;
    ValueNotifier<bool> isVisibleKeyboard = useState(true);
    useEffect(() {
      KeyboardVisibilityController keyboardVisibilityController =
          KeyboardVisibilityController();
      keyboardSubscription =
          keyboardVisibilityController.onChange.listen((bool visible) {
        isVisibleKeyboard.value = visible;
        //isVisibleKeyboard.value 
      });
      return () => keyboardSubscription.cancel();
    }, []);
    
  }
}

Upvotes: 0

hararot so
hararot so

Reputation: 161

Check the condition if the keyboard is open or not, you could use WidgetsBinding.instance.window.viewInsets.bottom , answered by Deepak Raj

OR you could use: KeyboardVisibilityBuilder

answered by Andrey Gordeev

KeyboardVisibilityBuilder(
    builder: (context, child, isKeyboardVisible) {
      if (isKeyboardVisible) {
        // when keyboard is visible
        return mChild;
      } else {
        // when keyboard is invisible
        return SizedBox.shrink();
      }
      
    },
    child: mChild,
  )

Upvotes: 1

Tom Berghuis
Tom Berghuis

Reputation: 571

I used the package keyboard_visibility

Then I wrapped my TextField with a KeyboardListener implemented as follows:

class KeyboardListener extends StatefulWidget {
  final Widget child;
  final void Function(bool) onChange;
  KeyboardListener({@required this.child, @required this.onChange});
  @override
  _KeyboardListenerState createState() => _KeyboardListenerState();
}

class _KeyboardListenerState extends State<KeyboardListener> {
  int _sId;
  KeyboardVisibilityNotification _kvn;

  @override
  void initState() {
    super.initState();
    _kvn = KeyboardVisibilityNotification();
    _sId = _kvn.addNewListener(
      onChange: widget.onChange,
    );
  }

  @override
  Widget build(BuildContext context) {
    return widget.child;
  }

  @override
  void dispose() {
    _kvn.removeListener(_sId);
    super.dispose();
  }
}

Upvotes: 3

Benjamin Menrad
Benjamin Menrad

Reputation: 988

You can use this simple check:

MediaQuery.of(context).viewInsets.bottom == 0

The keyboard is closed when this returns true, otherwise it's open. Be aware to take the context of the whole screen (Scaffold for example) and not only from one widget.

This is how you integrate that check to your code:

Visibility(
  child: Icon(Icons.add),
  visible: MediaQuery.of(context).viewInsets.bottom == 0,
)

Upvotes: 21

AlexPad
AlexPad

Reputation: 10879

You can use this library keyboard_visibility: ^0.5.6 at : https://pub.dev/packages/keyboard_visibility

For execute your code, insert this in the initState()

KeyboardVisibilityNotification.addNewListener( onChange: (bool visible) { print(visible); this.setState(() { keyboardIsOpen = visible; }); }, );

Whenever keyboard is open or closed, the library calls onChange method with the visibility boolean.

Upvotes: 2

Scaphae Studio
Scaphae Studio

Reputation: 551

A widget that calls a callback whenever the user presses or releases a key on a keyboard.

A RawKeyboardListener is useful for listening to raw key events and hardware buttons that are represented as keys. Typically used by games and other apps that use keyboards for purposes other than text entry.

For text entry, consider using a EditableText, which integrates with on-screen keyboards and input method editors (IMEs).

 const RawKeyboardListener({
Key key,
@required FocusNode focusNode,
@required ValueChanged<RawKeyEvent> onKey,
@required Widget child
})

Creates a widget that receives raw keyboard events.

For text entry, consider using a EditableText, which integrates with on-screen keyboards and input method editors (IMEs).

Implementation

const RawKeyboardListener({
  Key key,
  @required this.focusNode,
  @required this.onKey,
  @required this.child,
}) : assert(focusNode != null),
     assert(child != null),
     super(key: key);

Upvotes: -1

Hemanth Raj
Hemanth Raj

Reputation: 34769

The keyboard will automatically appear when the text field is focused. So you can add a listner to the focusnode to listen the focus change and hide respective widget.

Example:

    void _listener(){
        if(_myNode.hasFocus){
          // keyboard appeared 
        }else{
          // keyboard dismissed
        }
    }

    FocusNode _myNode = new FocusNode()..addListener(_listner);

    TextField _myTextField = new TextField(
            focusNode: _mynNode,
            ...
            ...
        );

    new Container(
        child: _myTextField
    );

Upvotes: 10

Related Questions