64

I am trying to add done button in number type input for a TextFormField in flutter but I could not able to do that.

TextFormField(
          key: Key(keyValue),
          initialValue: valueBuilder,
          onSaved: (text) {
            fieldsController.text = text.trim();
          },
          inputFormatters: [inputFormatters],
          keyboardType: TextInputType.phoneNumber,)

I want create a keyboard like the below. For the input text form field.

this

Ahmed Ashour
  • 5,179
  • 10
  • 35
  • 56
Praveen Ramalingam
  • 867
  • 2
  • 7
  • 14

10 Answers10

51

Change

keyboardType: TextInputType.number

to

keyboardType: TextInputType.numberWithOptions(signed: true, decimal: true)
Bob Lyons
  • 675
  • 5
  • 2
  • I think this is a good **temporary** workaround for a **built-in done button** on a **numeric keyboard** for **iOS**. – Giraldi May 11 '20 at 21:06
  • 2
    You only need `signed: true` to trigger this workaround. – Duncan Jones Jan 02 '21 at 12:12
  • 7
    with this solution there will be numbers and other characters on the keyboard, not just numbers – Giulio Pretis Apr 08 '22 at 12:08
  • @GiulioPretis Characters are shown but not clickable...so, it allows only Numbers & that is what required in this case. you can set **decimal** to **false** here if you want to use All characters from Standard Keyboard. – Shree Softech Jun 10 '22 at 06:48
20

You don't need a done button just wrap MaterialApp with a GestureDetector

GestureDetector(
  behavior: HitTestBehavior.opaque,
  onTap: () {
    FocusScopeNode currentFocus = FocusScope.of(context);

    if (!currentFocus.hasPrimaryFocus &&
        currentFocus.focusedChild != null) {
      FocusManager.instance.primaryFocus.unfocus();
    }
  },
  child: MaterialApp(
     title: "My title",
     home:MyHomeScreen(),
     ),
);
Toheeb
  • 1,217
  • 1
  • 14
  • 26
  • The method 'unfocus' can't be unconditionally invoked because the receiver can be 'null'. - i got this error – Aristidios Jul 20 '21 at 16:19
  • That's the way to go! Thanks a lot. But I want to add one more thing. I think behavior should be set as HitTestBehavior.translucent – batuhankrbb Aug 24 '21 at 04:57
  • Depending on your flutter version. If ```HitTestBehavior.translucent``` works for you then it's fine. I hope you're not doing that because you saw the warning on your console. this worked perfectly on ```flutter 1.2``` – Toheeb Aug 25 '21 at 17:00
  • 2
    This will make the app pretty janky, best to use this sparingly around root view widgets. – Oliver Dixon May 21 '22 at 11:08
16

I've just created a package for add basic actions to the current keyboards .

enter image description here

You can take a look here :

https://pub.dartlang.org/packages/keyboard_actions

Usage :

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

     //...
      FocusNode _nodeText1 = FocusNode();
      FocusNode _nodeText2 = FocusNode();
      FocusNode _nodeText3 = FocusNode();
      FocusNode _nodeText4 = FocusNode();
      FocusNode _nodeText5 = FocusNode();

     @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text("Keyboard Actions Sample"),
          ),
          body: FormKeyboardActions(
            keyboardActionsPlatform: KeyboardActionsPlatform.ALL, //optional
            keyboardBarColor: Colors.grey[200], //optional
            nextFocus: true, //optional
            actions: [
              KeyboardAction(
                focusNode: _nodeText1,
              ),
              KeyboardAction(
                focusNode: _nodeText2,
                closeWidget: IconButton(
                  icon: Icon(Icons.close),
                  onPressed: () {},
                ),
              ),
              KeyboardAction(
                focusNode: _nodeText3,
                onTapAction: () {
                  showDialog(
                      context: context,
                      builder: (context) {
                        return AlertDialog(
                          content: Text("Custom Action"),
                          actions: <Widget>[
                            FlatButton(
                              child: Text("OK"),
                              onPressed: () => Navigator.of(context).pop(),
                            )
                          ],
                        );
                      });
                },
              ),
              KeyboardAction(
                focusNode: _nodeText4,
                displayCloseWidget: false,
              ),
              KeyboardAction(
                focusNode: _nodeText5,
                closeWidget: Padding(
                  padding: EdgeInsets.all(5.0),
                  child: Text("CLOSE"),
                ),
              ),
            ],
            child: Padding(
              padding: const EdgeInsets.all(15.0),
              child: SingleChildScrollView(
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.stretch,
                  children: <Widget>[
                    TextField(
                      keyboardType: TextInputType.number,
                      focusNode: _nodeText1,
                      decoration: InputDecoration(
                        hintText: "Input Number",
                      ),
                    ),
                    TextField(
                      keyboardType: TextInputType.text,
                      focusNode: _nodeText2,
                      decoration: InputDecoration(
                        hintText: "Input Text with Custom Close Widget",
                      ),
                    ),
                    TextField(
                      keyboardType: TextInputType.number,
                      focusNode: _nodeText3,
                      decoration: InputDecoration(
                        hintText: "Input Number with Custom Action",
                      ),
                    ),
                    TextField(
                      keyboardType: TextInputType.text,
                      focusNode: _nodeText4,
                      decoration: InputDecoration(
                        hintText: "Input Text without Close Widget",
                      ),
                    ),
                    TextField(
                      keyboardType: TextInputType.number,
                      focusNode: _nodeText5,
                      decoration: InputDecoration(
                        hintText: "Input Number with Custom Close Widget",
                      ),
                    ),
                  ],
                ),
              ),
            ),
          ),
        );
      }
diegoveloper
  • 93,875
  • 20
  • 236
  • 194
  • 1
    There really isn't a whole lot of explanation on the pub page. Just a bunch of code. Flutter pros will be ok I guess, but the README is not very beginner friendly. – OjayChima Jun 23 '22 at 15:29
13

add this to your TextField

TextField(
...
keyboardType: TextInputType.numberWithOptions(signed: true),
inputFormatters: [
    FilteringTextInputFormatter.digitsOnly,
],
...
),
Kamal Panara
  • 482
  • 7
  • 16
13

This is how to add Done button to your TextFormField when keyboard is opened:

textInputAction: TextInputAction.done,

Please keep in mind that iOS doesn’t support Done on NUMERIC keyboards.

Osama Remlawi
  • 2,356
  • 20
  • 21
5

I used this way to handle done button in IOS

      keyboardType: Platform.isIOS? 
                    TextInputType.numberWithOptions(signed: true, decimal: true)
                  : TextInputType.number,
// This regex for only amount (price). you can create your own regex based on your requirement
     inputFormatters: [FilteringTextInputFormatter.allow(RegExp(r'^\d+\.?\d{0,4}'))],
BIS Tech
  • 17,000
  • 12
  • 99
  • 148
2

There is no done button in ios keyboard. Solution is that use "keyboard_actions" plugin otherwise add layout top of keyboard check this

https://blog.usejournal.com/keyboard-done-button-ux-in-flutter-ios-app-3b29ad46bacc

1

I used the signed option to display the done button. Then I used a TextInputFormatter with a RegEx to limit what the user can input.

new TextFormField(
              controller: myController,
              keyboardType: TextInputType.numberWithOptions(signed:true, decimal: true),
              textInputAction: TextInputAction.done,
              onFieldSubmitted: (term) {
                _showSnackBar(context, double.parse(myController.text));
              },
              onEditingComplete: () {
                _showSnackBar(context, double.parse(myController.text));
              },
              decoration: const InputDecoration(
                helperText: "Actual",
                hintText: "Units used",
                border: UnderlineInputBorder(),
                icon: Icon(Icons.keyboard),
              ),
              inputFormatters: <TextInputFormatter>[
                FilteringTextInputFormatter.allow(RegExp(r'^\d*\.?\d*$')),
              ],
            ),
Nicolas
  • 156
  • 2
  • 2
0

You can add a done button on the bottomSheet of Scaffold.

Example

import 'package:flutter/material.dart';
class MyPage extends StatefulWidget {
  const MyPage({super.key});

  @override
  State<MyPage> createState() => _MyPageState();
 }

 class _MyPageState extends State<MyPage> {
@override
Widget build(BuildContext context) {
return Scaffold(
  bottomSheet: MediaQuery.of(context).viewInsets.bottom == 0
      ? null
      : Row(
          children: [
            const Spacer(),
            TextButton(
                onPressed: () {
                  FocusManager.instance.primaryFocus?.unfocus();
                },
                child: const Text("Done"))
          ],
        ),
  appBar: AppBar(
    backgroundColor: Theme.of(context).colorScheme.inversePrimary,
    title: const Text("Keyboard done button"),
  ),
  body: ListView(
    padding: const EdgeInsets.all(8),
    keyboardDismissBehavior: ScrollViewKeyboardDismissBehavior.onDrag,
    children: [
      TextFormField(
        decoration: const InputDecoration(
          labelText: 'Some text',
        ),
      ),
    ],
  ),
);
}
}
Shoaib
  • 1,295
  • 15
  • 22
-3

There is no done button in iOS but we can check the length of the input and clear focus to hide the numberpad keyboard. Implement like below,(it'll work with fix length of number value)

onChanged: (val) {
        if (val.length == 10) { //10 is the length of the phone number you're allowing
          FocusScope.of(context).requestFocus(FocusNode());
        }
      }
Purvik Rana
  • 331
  • 7
  • 17