Flutter Hide keyboard

Original answer: https://stackoverflow.com/questions/44991968/how-can-i-dismiss-the-on-screen-keyboard

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

Using with BLoC

  • In BLoC, create FocusNode, and set unfocus at any time you need to hide the keyboard
final FocusNode focusNode = FocusNode();
  • In Widget, get focusNode directly via BLoC, or for safety you should create a method called hideKeyboard() on BLoC and use it to avoid using focusNode ref
onTap: () {
  bloc.focusNode.unfocus();
}

or with TextField
child: TextField(
  onChanged: bloc.searchUser.push,
  autofocus: true,
  focusNode: bloc.focusNode,
  decoration: InputDecoration(
    border: InputBorder.none,
    hintText: 'Please enter a search term',
  ),
),

Completed demo: Create a search screen, user give an input text, the app fetch from github api to get data.

Search widget

import 'package:bflutter_poc/detail/detail_screen.dart';
import 'package:bflutter_poc/model/user_base.dart';
import 'package:bflutter_poc/search/search_bloc.dart';
import 'package:flutter/material.dart';


class SearchScreen extends StatefulWidget {
  @override
  _SearchScreenState createState() => _SearchScreenState();
}


class _SearchScreenState extends State<SearchScreen> {
  final bloc = SearchBloc();


  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Search Screen')),
      body: Container(
          child: GestureDetector(
        onTap: () {
          bloc.focusNode.unfocus();
        },
        child: Column(
          children: <Widget>[
            Container(
              margin: EdgeInsets.only(left: 10, right: 10, top: 10),
              child: Row(
                children: <Widget>[
                  Icon(Icons.search),
                  Expanded(
                    child: TextField(
                      onChanged: bloc.searchUser.push,
                      autofocus: true,
                      focusNode: bloc.focusNode,
                      decoration: InputDecoration(
                        border: InputBorder.none,
                        hintText: 'Please enter a search term',
                      ),
                    ),
                  ),
                ],
              ),
            ),
            Container(
              margin: EdgeInsets.only(bottom: 10),
              child: Divider(
                color: Colors.black,
              ),
            ),
            Container(
              child: StreamBuilder(
                stream: bloc.loading.stream(),
                builder: (context, loading) {
                  if (loading.hasData && loading.data) {
                    return Center(
                      child: CircularProgressIndicator(),
                    );
                  }
                  return Container();
                },
              ),
            ),
            Expanded(
              child: StreamBuilder(
                stream: bloc.searchUser.stream(),
                builder: (context, snapshot) {
                  if (snapshot.hasError) {
                    return Text(snapshot.error.toString());
                  }
                  if (!snapshot.hasData || (snapshot?.data)?.length == 0) {
                    return Text('No data');
                  }
                  List<UserBase> users = snapshot.data;
                  return ListView.builder(
                    itemCount: users.length,
                    itemBuilder: (BuildContext context, int index) {
                      return FlatButton(
                        child: Row(
                          children: <Widget>[
                            CircleAvatar(
                              backgroundImage:
                                  NetworkImage(users[index].avatarUrl),
                              radius: 20.0,
                            ),
                            Padding(
                              padding: EdgeInsets.only(left: 10, right: 10),
                              child: Text('${users[index].login}'),
                            ),
                          ],
                        ),
                        onPressed: () {
                          Navigator.push(
                              context,
                              MaterialPageRoute(
                                  builder: (context) =>
                                      DetailScreen(userBase: users[index])));
                        },
                      );
                    },
                  );
                },
              ),
            ),
          ],
        ),
      )),
    );
  }
}

Search Bloc

import 'dart:convert';

import 'package:bflutter/bflutter.dart';
import 'package:bflutter_poc/api.dart';
import 'package:bflutter_poc/model/user_base.dart';
import 'package:flutter/material.dart';
import 'package:rxdart/rxdart.dart';

class SearchBloc {
  final loading = BlocDefault<bool>();
  final searchUser = Bloc<String, List<UserBase>>();
  final FocusNode focusNode = FocusNode();

  SearchBloc() {
    _initSearchUserLogic();
  }

  void _initSearchUserLogic() {
    searchUser.business = (Observable<String> event) => event
            .distinct()
            .debounceTime(Duration(milliseconds: 1000))
            .flatMap((input) {
          //show loading
          loading.push(true);
          if (input.isEmpty) return Observable.just(null);
          //hide keyboard
          focusNode.unfocus();
          return Observable.fromFuture(Api().searchUsers(input));
        }).map((data) {
          if (data == null) {
            return <UserBase>[];
          }

          if (data.statusCode == 200) {
            final List<UserBase> result = json
                .decode(data.body)['items']
                .cast<Map<String, dynamic>>()
                .map<UserBase>((item) => UserBase.fromJson(item))
                .toList();
            return result;
          } else {
            throw (data.body);
          }
        }).handleError((error) {
          loading.push(false);
          throw error;
        }).doOnData((data) {
          loading.push(false);
        });
  }

  void dispose() {
    loading.dispose();
    searchUser.dispose();
  }
}

Leave a Reply

Your email address will not be published.Required fields are marked *