Do you miss Blackberry phones? I do. They had a full QWERTY keyboard, and it was so easy to type. I wish they had evolved with time, with the operating system. We would be seeing some great innovations with its physical keyboards and touch screen devices.
Instead, we programmers and designers are confronted with a particular modern challenge: the soft keyboard. Mobile app developers must keep in mind that the keyboard on phones is constantly hidden from view.
As a result, the UI designer must be significantly more careful. When the keyboard appears, it should not obscure other sections of the UI while entering data into a specific widget.
Then there are various devices with diverse screen sizes. Consider two types of devices right now: iOS and Android. Android smartphones contain physical or soft buttons used to navigate the software. On iOS devices, closing or switching between applications is currently accomplished with a single swipe from the bottom to the top.
When it comes to keyboard management on both devices, tapping on a widget that allows data input opens the keyboard from the bottom of the screen. The real problem arises now on how to close the keyboard when not in use or give the user enough control over the keyboard opening and closing.
Android devices have a solution; press the physical back button (provided on some mobile phones) or the soft key back button, and it closes the keyboard. But what about the iOS devices? On iPhones, if the user swipes from the bottom towards the top, it will close the application entirely or switch between applications. On iPads, there is a button on the bottom right corner for minimizing the keyboard or closing the keyboard.
Flutter being a multi-platform framework, how do we solve this problem of opening and closing the keyboard to be consistent with the application across all devices?
Based on my research and experience, I offer this solution for:
Some of the Flutter widgets that offer input of texts and numbers are:
The most common screens where a programmer would use these widgets are for login and signup screens. If the application requires filling a form with user data, there might be more text fields on that screen. Some might need only text input, and some only numbers or both. Tapping on these widgets will cause the keyboard to open.
If you create something similar to the above screen, you must remember that it will push the widget upward when the keyboard opens, causing an overflow error. To solve this, you need to wrap the widgets in a SingleChildScrollView or a ListView, depending on your UI.
When you wrap your widget with SingleChildScrollView or ListView, both widgets have a property called keyboardDismissBehavior
. It represents how a ScrollView should dismiss the onscreen keyboard.
In addition, it has two types of drag behavior: a manual where it is up to the user to dismiss the keyboard, and onDrag
where the keyboard gets dismissed when the user starts to drag on the screen.
SingleChildScrollView( keyboardDismissBehavior: ScrollViewKeyboardDismissBehavior.onDrag, child: Padding( padding: const EdgeInsets.symmetric( vertical: Sizes.dimen_20, horizontal: Sizes.dimen_14), child: Column( children: [ TextFormField( controller: _studentNameController, keyboardType: TextInputType.name, textCapitalization: TextCapitalization.words, textInputAction: TextInputAction.next, decoration: kTextInputDecoration.copyWith(labelText:'Student Name'), ),
Another method to dismiss the keyboard is to wrap your whole view, meaning the parent widget most commonly used is the Scaffold widget or SafeArea with the GestureDetector. Inside its onTap
property, you have to pass an unfocus
function, which removes the focus from the current node and moves its primary focus to another node.
To better understand when the keyboard is open, the primary focus is on the keyboard. When you click anywhere else on the screen, the GestureDetector removes the focus from the keyboard and shifts its primary focus on the view, which eventually closes the keyboard.
@override Widget build(BuildContext context) { return GestureDetector( //onTap: () => FocusScope.of(context).unfocus(), /// > flutter 2.0 onTap: () => FocusManager.instance.primaryFocus?.unfocus(), child: Scaffold( resizeToAvoidBottomInset: true, appBar: AppBar( title: const Text('Keyboard Open and Close'), ), body: ListView( padding: const EdgeInsets.all(14.0), shrinkWrap: true, keyboardDismissBehavior: ScrollViewKeyboardDismissBehavior.onDrag, children: [ TextFormField( controller: _studentNameController, keyboardType: TextInputType.name, textCapitalization: TextCapitalization.words, textInputAction: TextInputAction.next, decoration: kTextInputDecoration.copyWith(labelText: 'Student Name'),),
You might be wondering whether it is advisable to use the GestureDetector on the whole view. According to the documentation, it is safe to call regardless of whether the view ever requested focus or not.
However, nothing happens if it does have focus or primary focus. To fully understand this action, when the user clicks anywhere else on the screen beside the text field widget, nothing happens visually anywhere else on the screen except the closing of the keyboard.
If you have more than one text field widget on any of your screens, the textInputAction
property will help you a lot with user experience. Therefore, I advise you to pass (TextInputAction.next)
for every text field.
Then, instead of the Enter button on the keyboard, you will see the Next button. When the user finishes entering data in the first text field, clicking on the Next button will directly take the user to the following text field widget without extra touch input. This action also prevents the keyboard from closing and opening when focus changes from one text field to another.
TextFormField( controller: _fatherNameController, keyboardType: TextInputType.name, textCapitalization: TextCapitalization.words, textInputAction: TextInputAction.next, decoration: kTextInputDecoration.copyWith(labelText: 'Father Name'), ),
User interface and user experience are inextricably linked. We should be more concerned with the user experience as programmers since it doesn’t matter how appealing the application looks if the user finds it difficult to interact with. Once the UX is solved, the UI will be an extra benefit to the overall application experience.
The mobile application’s user experience includes opening and closing the keyboard. When should it be opened? Should it open when the screen appears or when the user taps the screen? And when should the keyboard be closed? Is the keyboard obstructing something on the screen when it opens, such as the widget where the user wants to enter data?
There are so many things happening, and there are so many things to think about on a single screen just focusing on keyboard opening and closing.
There is always a problem, and I have written two possible solutions for opening and closing the soft keyboard on smartphones using the Flutter framework. Hopefully, you will be using those solutions for your next project, and if you come up with a better solution than I have provided, I would love to hear about it. I love discovering new things in Flutter, which requires a little bit of experimentation.
Thank you! Stay safe!
Install LogRocket via npm or script tag. LogRocket.init()
must be called client-side, not
server-side
$ npm i --save logrocket // Code: import LogRocket from 'logrocket'; LogRocket.init('app/id');
// Add to your HTML: <script src="https://cdn.lr-ingest.com/LogRocket.min.js"></script> <script>window.LogRocket && window.LogRocket.init('app/id');</script>
Hey there, want to help make our blog better?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowCompare Prisma and Drizzle ORMs to learn their differences, strengths, and weaknesses for data access and migrations.
It’s easy for devs to default to JavaScript to fix every problem. Let’s use the RoLP to find simpler alternatives with HTML and CSS.
Learn how to manage memory leaks in Rust, avoid unsafe behavior, and use tools like weak references to ensure efficient programs.
Bypass anti-bot measures in Node.js with curl-impersonate. Learn how it mimics browsers to overcome bot detection for web scraping.