Як я можу відхилити екранну клавіатуру?


139

Я збираю введення користувача за допомогою TextFormFieldі, коли користувач натискає на FloatingActionButtonвказівку на те, що вони зроблені, я хочу відхилити екранна клавіатура.

Як змусити клавіатуру автоматично вимикатись?

import 'package:flutter/material.dart';

class MyHomePage extends StatefulWidget {
  MyHomePageState createState() => new MyHomePageState();
}

class MyHomePageState extends State<MyHomePage> {
  TextEditingController _controller = new TextEditingController();

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(),
      floatingActionButton: new FloatingActionButton(
        child: new Icon(Icons.send),
        onPressed: () {
          setState(() {
            // send message
            // dismiss on screen keyboard here
            _controller.clear();
          });
        },
      ),
      body: new Container(
        alignment: FractionalOffset.center,
        padding: new EdgeInsets.all(20.0),
        child: new TextFormField(
          controller: _controller,
          decoration: new InputDecoration(labelText: 'Example Text'),
        ),
      ),
    );
  }
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      home: new MyHomePage(),
    );
  }
}

void main() {
  runApp(new MyApp());
}

Коллін, Друга відповідь від @Pascal має бути оновленою, виправленою відповіддю.
Джек

Відповіді:


230

Щодо Flutter v1.7.8 + виправлення.2, шлях:

FocusScope.of(context).unfocus()

Прокоментуйте PR щодо цього:

Тепер, коли # 31909 (be75fb3) приземлився, вам слід скористатись FocusScope.of(context).unfocus()замість FocusScope.of(context).requestFocus(FocusNode()), оскільки FocusNodes є ChangeNotifiers, і слід розмістити належним чином.

-> НЕ використовуйте ̶r̶e̶q̶u̶e̶s̶t̶F̶o̶c̶u̶s̶(̶F̶o̶c̶u̶s̶N̶o̶d̶e̶(̶)̶більше.

 F̶o̶c̶u̶s̶S̶c̶o̶p̶e̶.̶o̶f̶(̶c̶o̶n̶t̶e̶x̶t̶)̶.̶r̶e̶q̶u̶e̶s̶t̶F̶o̶c̶u̶s̶(̶F̶o̶c̶u̶s̶N̶o̶d̶e̶(̶)̶)̶;̶

1
Працював для мене на виправлення v1.7.8 + виправлення.4
Rajesh Jr.

2
працюйте для мене, цю відповідь слід замаскувати як правильну
user3087360

@kine, ви можете, будь ласка, детальніше? А на документацію, це так робити (див. Api.flutter.dev/flutter/widgets/FocusNode/unfocus.html )
Паскаль

@Pascal Так, я прочитав документацію, і це було б моїм кращим рішенням, але в моєму додатку воно працює не завжди (досить складна форма з декількома TextFieldвіджетами s та іншими редакторами). Я не знаю, чому, але іноді unfocusне має жодного ефекту. Заміна його прийнятим рішенням (жодних інших змін) не усуває проблему. Можливо, це пов’язано з місцем, звідки unfocusдзвонять. Мені потрібно зателефонувати, наприклад, з CheckBoxListTile.onChangedвідхилення клавіатури, коли користувач взаємодіє з віджетом прапорця та з інших подібних місць. Я не пам’ятаю точного місця випуску.
Кін

@kine Дякую за пояснення. Надання прикладу команді Flutter було б дивним ;-)
Паскаль

208

Примітка. Ця відповідь застаріла. Дивіться відповідь на новіші версії Flutter .

Ви можете відхилити клавіатуру, відібравши фокус TextFormFieldта віддавши його невикористаному FocusNode:

FocusScope.of(context).requestFocus(FocusNode());

Де б ви реалізували цей код? В TextFormField; можливо, після onChanged:або в дії вашої спеціальної кнопки?
Чарльз-молодший

@CharlesJr Я це роблю в дії своєї кнопки.
Дункан Джонс

Ви можете використовувати мій пакет, якщо хочете :) pub.dartlang.org/packages/keyboard_action
diegoveloper

17
Це, перш ніж Flutter v1.7.8 - см відповідь stackoverflow.com/a/56946311/8696915 , який даєFocusScope.of(context).unfocus()
Річард Джонсон

1
Не робіть цього, якщо у вас є доступ до .unfocus (), оскільки це спричинить витік пам'яті. Цей новий FocusNode () ніколи не очиститься. Дивіться коментар про .unfocus ()
Майкл Петерсон

70

Рішення з FocusScope не працює для мене. Я знайшов інше:

import 'package:flutter/services.dart';

SystemChannels.textInput.invokeMethod('TextInput.hide');

Це вирішило мою проблему.


Якщо зателефонувати цьому, клавіатура для мене не приховує. Чи повинен він працювати як на Android, так і на iOS?
Жардо

Працював для мене на iOS (12.1, iPhone 5s) та Android (Pixel 3)
Jannie Theunissen

Куди ти це поклав? Я спробував просто додати його як перший біт коду в додатку, і він нічого не зробив.
Justin808

Що ви маєте на увазі - «перший біт коду»? buildНаприклад, вставте його в метод.
Андрій Турковський,

1
чи існує еквівалент цього для цифрової клавіатури?
Данило Максимович

19

Для Flutter 1.17.3 (стабільний канал станом на червень 2020 року) використовуйте

FocusManager.instance.primaryFocus.unfocus();

12

Жодне з перерахованих вище рішень для мене не працює.

Flutter пропонує це - Помістіть ваш віджет всередину нового GestureDetector (), на якому натисніть, щоб приховати клавіатуру і onTap використовувати FocusScope.of (контекст) .requestFocus (новий FocusNode ())

class Home extends StatelessWidget {
@override
  Widget build(BuildContext context) {
    var widget = new MaterialApp(
        home: new Scaffold(
            body: new Container(
                height:500.0,
                child: new GestureDetector(
                    onTap: () {
                        FocusScope.of(context).requestFocus(new FocusNode());
                    },
                    child: new Container(
                        color: Colors.white,
                        child:  new Column(
                            mainAxisAlignment:  MainAxisAlignment.center,
                            crossAxisAlignment: CrossAxisAlignment.center,

                            children: [
                                new TextField( ),
                                new Text("Test"),                                
                            ],
                        )
                    )
                )
            )
        ),
    );

    return widget;
}}

12

Наступний код допоміг мені приховати клавіатуру

   void initState() {
   SystemChannels.textInput.invokeMethod('TextInput.hide');
   super.initState();
   }


8
GestureDetector(
          onTap: () {
            FocusScope.of(context).unfocus();
          },
          child:Container(
    alignment: FractionalOffset.center,
    padding: new EdgeInsets.all(20.0),
    child: new TextFormField(
      controller: _controller,
      decoration: new InputDecoration(labelText: 'Example Text'),
    ),
  ), })

спробуйте це на жесті крана


Дякую ... прийняв це рішення
Аджай Кумар

6

Оскільки у Flutter все є віджетом, я вирішив обернути SystemChannels.textInput.invokeMethod('TextInput.hide');і FocusScope.of(context).requestFocus(FocusNode());підхід у короткий модуль корисності з віджетом і міксином в ньому.

За допомогою віджета ви можете обгорнути будь-який віджет (що дуже зручно при використанні хорошої підтримки IDE) за допомогою KeyboardHiderвіджета:

class SimpleWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return KeyboardHider(
      /* Here comes a widget tree that eventually opens the keyboard,
       * but the widget that opened the keyboard doesn't necessarily
       * takes care of hiding it, so we wrap everything in a
       * KeyboardHider widget */
      child: Container(),
    );
  }
}

За допомогою mixin ви можете викликати приховування клавіатури від будь-якого стану або віджета при будь-якій взаємодії:

class SimpleWidget extends StatefulWidget {
  @override
  _SimpleWidgetState createState() => _SimpleWidgetState();
}

class _SimpleWidgetState extends State<SimpleWidget> with KeyboardHiderMixin {
  @override
  Widget build(BuildContext context) {
    return RaisedButton(
      onPressed: () {
        // Hide the keyboard:
        hideKeyboard();
        // Do other stuff, for example:
        // Update the state, make an HTTP request, ...
      },
    );
  }
}

Просто створіть keyboard_hider.dartфайл, і віджет і mixin готові до використання:

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

/// Mixin that enables hiding the keyboard easily upon any interaction or logic
/// from any class.
abstract class KeyboardHiderMixin {
  void hideKeyboard({
    BuildContext context,
    bool hideTextInput = true,
    bool requestFocusNode = true,
  }) {
    if (hideTextInput) {
      SystemChannels.textInput.invokeMethod('TextInput.hide');
    }
    if (context != null && requestFocusNode) {
      FocusScope.of(context).requestFocus(FocusNode());
    }
  }
}

/// A widget that can be used to hide the text input that are opened by text
/// fields automatically on tap.
///
/// Delegates to [KeyboardHiderMixin] for hiding the keyboard on tap.
class KeyboardHider extends StatelessWidget with KeyboardHiderMixin {
  final Widget child;

  /// Decide whether to use
  /// `SystemChannels.textInput.invokeMethod('TextInput.hide');`
  /// to hide the keyboard
  final bool hideTextInput;
  final bool requestFocusNode;

  /// One of hideTextInput or requestFocusNode must be true, otherwise using the
  /// widget is pointless as it will not even try to hide the keyboard.
  const KeyboardHider({
    Key key,
    @required this.child,
    this.hideTextInput = true,
    this.requestFocusNode = true,
  })  : assert(child != null),
        assert(hideTextInput || requestFocusNode),
        super(key: key);

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      behavior: HitTestBehavior.opaque,
      onTap: () {
        hideKeyboard(
          context: context,
          hideTextInput: hideTextInput,
          requestFocusNode: requestFocusNode,
        );
      },
      child: child,
    );
  }
}

4

Ви можете використовувати unfocus()метод з FocusNodeкласу.

import 'package:flutter/material.dart';

class MyHomePage extends StatefulWidget {
  MyHomePageState createState() => new MyHomePageState();
}

class MyHomePageState extends State<MyHomePage> {
  TextEditingController _controller = new TextEditingController();
  FocusNode _focusNode = new FocusNode(); //1 - declare and initialize variable

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(),
      floatingActionButton: new FloatingActionButton(
        child: new Icon(Icons.send),
        onPressed: () {
            _focusNode.unfocus(); //3 - call this method here
        },
      ),
      body: new Container(
        alignment: FractionalOffset.center,
        padding: new EdgeInsets.all(20.0),
        child: new TextFormField(
          controller: _controller,
          focusNode: _focusNode, //2 - assign it to your TextFormField
          decoration: new InputDecoration(labelText: 'Example Text'),
        ),
      ),
    );
  }
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      home: new MyHomePage(),
    );
  }
}

void main() {
  runApp(new MyApp());
}

1
Привіт! Було б найкраще, якби ви могли змінити свою відповідь, щоб додати лише трохи більше контексту до своєї відповіді.
grooveplex

1
Найкраще рішення з найменшою кількістю кодування
Вал

Так, фокус видаляється, якщо натиснути певний віджет. Неможливо додати його до кожного віджета в моєму додатку.
Дпедрінья

Торкніться віджета - це лише один із способів виклику unfocus. Якщо ви не хочете спамувати це на своєму додатку, ви можете скористатися іншим способом, наприклад TextFormFieldподією зміни або реактивним шаблоном, це залежить від архітектури вашого додатка.
Евандро Ап. S.

4

Схоже, різні підходи для різної версії. Я використовую Flutter v1.17.1, і нижче працює для мене.

onTap: () {
    FocusScopeNode currentFocus = FocusScope.of(context);
    if (!currentFocus.hasPrimaryFocus && currentFocus.focusedChild != null) {
       currentFocus.focusedChild.unfocus();
    }
}

1
_dismissKeyboard(BuildContext context) {
   FocusScope.of(context).requestFocus(new FocusNode());
}

@override
Widget build(BuildContext context) {

return new GestureDetector(
    onTap: () {
    this._dismissKeyboard(context);
    },
    child: new Container(
    color: Colors.white,
    child: new Column(
        children: <Widget>[/*...*/],
    ),
    ),
 );
}

0

спробуйте скористатися контролером редагування тексту. спочатку,

    final myController = TextEditingController();
     @override
  void dispose() {
    // Clean up the controller when the widget is disposed.
    myController.dispose();
    super.dispose();
  }

і в події на прес,

onPressed: () {
            commentController.clear();}

це відхилить клавіатуру.


-1

Підводячи підсумок, це робоче рішення для Flutter 1.17:

Оберніть свій віджет так:

GestureDetector(
        onTap: FocusScope.of(context).unfocus,
        child: YourWidget(),
);
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.