Ekran klavyesini nasıl kapatabilirim?


140

Kullanıcı girdisini a ile topluyorum TextFormFieldve kullanıcı FloatingActionButtonyaptıklarını belirten bir a bastığında, ekran klavyesini kapatmak istiyorum.

Klavyenin otomatik olarak kapanmasını nasıl sağlarım?

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());
}

Collin, @Pascal'dan gelen ikinci cevap güncellenmiş, düzeltilmiş cevap olmalıdır.
Jack

Yanıtlar:


235

Flutter v1.7.8 + düzeltme.2'den itibaren, gitmenin yolu:

FocusScope.of(context).unfocus()

PR hakkında yorum yapın :

Şimdi # 31909 (be75fb3) indi ettiğini, kullanmak gerekir FocusScope.of(context).unfocus()yerine FocusScope.of(context).requestFocus(FocusNode())beri, FocusNodes vardır ChangeNotifiersve uygun şekilde atılmalıdır.

-> YAPMAYIN kullanmak ̶r̶e̶q̶u̶e̶s̶t̶F̶o̶c̶u̶s̶(̶F̶o̶c̶u̶s̶N̶o̶d̶e̶(̶)̶artık.

 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
Benim için v1.7.8 düzeltmesi + düzeltme.4 üzerinde çalıştı
Rajesh Jr.

2
benim için çalış, bu cevap doğru cevap olarak maskelenmeli
user3087360

@kine detaylandırır mısın lütfen? Belgelere göre, bunu yapmanın yolu budur (bkz. Api.flutter.dev/flutter/widgets/FocusNode/unfocus.html )
Pascal

@Pascal Evet Belgeleri okudum ve bu benim tercih ettiğim çözüm olurdu, ancak uygulamamda her zaman çalışmıyor (birkaç TextFields ve diğer düzenleme widget'ları ile oldukça karmaşık bir form ). Neden bilmiyorum ama bazen unfocusbir etkisi olmuyor. Bunu kabul edilen çözümle (başka değişiklik yapılmadan) değiştirmek sorunu çözer. Belki de unfocusçağrıldığı yerle ilgilidir . CheckBoxListTile.onChangedKullanıcı bir onay kutusu widget'ıyla etkileşime girdiğinde klavyeyi kapatmak için ve diğer benzer konumlardan buna örn . Sorunun tam yerini hatırlamıyorum.
kine

@kine Açıklama için teşekkürler. Flutter ekibine bir örnek vermek harika olurdu ;-)
Pascal

211

Not: Bu cevap güncel değildir. Flutter'ın daha yeni sürümleri için cevaba bakın .

Klavyeyi, odak noktasını alıp TextFormFieldkullanılmayan birine vererek kapatabilirsiniz FocusNode:

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

Bu kodu nereye uygularsınız? TextFormField içinde; onChanged:özel düğmenizden sonra veya eylem sırasında olabilir mi?
Charles Jr

@CharlesJr Bunu düğmemle yapıyorum.
Duncan Jones

isterseniz paketimi kullanabilirsiniz :) pub.dartlang.org/packages/keyboard_actions
diegoveloper

17
Cevap bkz - Bu Flutter v1.7.8 öncedir stackoverflow.com/a/56946311/8696915 verirFocusScope.of(context).unfocus()
Richard Johnson

1
.Unfocus () 'a erişiminiz varsa bunu yapmayın çünkü bu bir bellek sızıntısına neden olur. Bu yeni FocusNode () asla temizlenmeyecek. .Unfocus ()
Michael Peterson

70

FocusScope ile çözüm benim için işe yaramıyor. Başka buldum:

import 'package:flutter/services.dart';

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

Sorunumu çözdü.


Bunu aramak klavyeyi benim için gizlemez. Hem Android hem de iOS'ta çalışmalı mı?
Jardo

Benim için iOS (12.1, iPhone 5s) ve Android (Pixel 3) üzerinde çalıştı
Jannie Theunissen

Bunu nereye koyuyorsunuz? Uygulamadaki ilk kod parçası olarak eklemeyi denedim ve hiçbir şey yapmadı.
Justin808

Ne demek - "ilk kod parçası"? buildÖrneğin yönteme ekleyin .
Andrey Turkovsky

1
sayısal tuş takımı için bunun bir eşdeğeri var mı?
Daniel Maksimovich

21

Flutter 1.17.3 için (Haziran 2020 itibarıyla kararlı kanal), şunu kullanın:

FocusManager.instance.primaryFocus.unfocus();


12

Yukarıdaki çözümlerin hiçbiri benim için çalışmıyor.

Flutter bunu öneriyor - Widget'ınızı yeni GestureDetector () içine koyun ve üzerine dokunarak klavyeyi gizleyin ve onTap FocusScope.of (bağlam) .requestFocus (yeni 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

Aşağıdaki kod klavyeyi gizlememe yardımcı oldu

   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'),
    ),
  ), })

bunu dokunma hareketinde dene


Teşekkürler ... bu çözümü
Ajay Kumar

6

Flutter'da olduğu gibi her şey bir widget'tır, SystemChannels.textInput.invokeMethod('TextInput.hide');ve FocusScope.of(context).requestFocus(FocusNode());yaklaşımını bir widget ve içinde bir mixin bulunan kısa bir yardımcı program modülüne yerleştirmeye karar verdim .

Widget ile herhangi bir widget'ı (iyi bir IDE desteği kullanırken çok kullanışlı) widget ile sarmalayabilirsiniz 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 ile, herhangi bir etkileşim üzerine klavyeyi herhangi bir durumdan veya widget'tan gizlemeyi tetikleyebilirsiniz:

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, ...
      },
    );
  }
}

Sadece bir keyboard_hider.dartdosya oluşturun ve widget ve mixin kullanıma hazırdır:

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

Sınıftan unfocus()yöntemi kullanabilirsiniz 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
Selam! Cevabınıza biraz daha fazla bağlam eklemek için cevabınızı düzenlerseniz en iyisi olur .
grooveplex

1
En az miktarda kodlama ile en iyi çözüm
Val

Evet, belirli bir parçacığa dokunulduğunda odağı kaldırır. Uygulamamdaki her widget'a ekleyemiyorum.
Dpedrinha

Bir parçacığa dokunmak, unfocusyöntemi çağırmanın yalnızca bir yoludur . Bunu uygulamanızda spam yapmak istemiyorsanız, TextFormFielddeğişiklik etkinliği veya reaktif bir model gibi farklı bir yol kullanabilirsiniz , bu, uygulamanızın mimarisine bağlıdır.
Evandro Ap. S.

4

Farklı sürümler için farklı yaklaşımlar gibi görünüyor. Flutter v1.17.1 kullanıyorum ve aşağıdaki benim için çalışıyor.

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

bir metin düzenleme denetleyicisi kullanmayı deneyin. başlangıçta,

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

ve basın etkinliğinde,

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

bu, klavyeyi kapatır.


0

Özetlemek gerekirse, bu Flutter 1.17 için çalışan bir çözümdür:

Widget'ınızı şu şekilde sarın:

GestureDetector(
        onTap: FocusScope.of(context).unfocus,
        child: YourWidget(),
);
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.