40

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
  • 4,462
  • 10
  • 33
  • 49
praveen r
  • 555
  • 1
  • 5
  • 11
  • Have you tried setting the `TextInputAction` on your form field? https://docs.flutter.io/flutter/services/TextInputAction-class.html – Alex Meuer Nov 27 '18 at 18:00
  • 4
    keyboardType: TextInputType.number, textInputAction: TextInputAction.done, – anmol.majhail Nov 27 '18 at 18:08
  • 3
    Yes but that is also not working in IOS platform since mac OS does not support such UI in number keyboard,so looking for a solution – praveen r Nov 28 '18 at 02:15
  • use - https://docs.flutter.io/flutter/cupertino/CupertinoTextField/CupertinoTextField.html – anmol.majhail Nov 28 '18 at 05:11
  • i am using textform field ,which is manily to easily do with the validation part of the field ,so replacing with cupertinoTextField will make my validation work harder – praveen r Nov 28 '18 at 05:43

9 Answers9

31

Change

keyboardType: TextInputType.number

to

keyboardType: TextInputType.numberWithOptions(signed: true, decimal: true)
Bob Lyons
  • 459
  • 4
  • 2
14

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
  • 750
  • 1
  • 8
  • 24
  • 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
  • This will make the app pretty janky, best to use this sparingly around root view widgets. – Oliver Dixon May 21 '22 at 11:08
13

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
  • 79,114
  • 19
  • 208
  • 182
11

add this to your TextField

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

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
  • 1,265
  • 13
  • 16
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

2

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
  • 12,833
  • 7
  • 71
  • 107
0

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
  • 96
  • 1
  • 2
-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
  • 323
  • 4
  • 15