Add features to the Android / iOS keyboard in a simple way.

Overview

Keyboard Actions

pub package

Add features to the Android / iOS keyboard in a simple way.

Because the keyboard that Android / iOS offers us specifically when we are in numeric mode, does not bring the button to hide the keyboard. This causes a lot of inconvenience for users, so this package allows adding functionality to the existing keyboard.

Features

  • Done button for the keyboard (You can customize the button).
  • Move up/down between your Textfields (You can hide for set nextFocus: false).
  • Keyboard Bar customization.
  • Custom footer widget below keyboard bar
  • Create your own Keyboard in an easy way
  • You can use it for Android, iOS or both platforms.
  • Compatible with Dialog.

Example of the custom footer:

Screen Shot 2019-05-22 at 5 46 50 PM

For more fun, use that widget as a custom keyboard with your custom input:

Screen Shot 2019-05-22 at 5 46 54 PM

Even more fun:

Watch the video

Getting started

You should ensure that you add the dependency in your flutter project.

dependencies:
  keyboard_actions: "^3.4.5"

You should then run flutter packages upgrade or update your packages in IntelliJ.

Example Project

There is an example project in the example folder where you can get more information. Check it out. Otherwise, keep reading to get up and running.

Usage

[ FlatButton( child: Text("OK"), onPressed: () => Navigator.of(context).pop(), ) ], ); }); }, ), KeyboardActionsItem( focusNode: _nodeText4, displayCloseWidget: false, ), KeyboardActionsItem( focusNode: _nodeText5, toolbarButtons: [ //button 1 (node) { return GestureDetector( onTap: () => node.unfocus(), child: Container( color: Colors.white, padding: EdgeInsets.all(8.0), child: Text( "CLOSE", style: TextStyle(color: Colors.black), ), ), ); }, //button 2 (node) { return GestureDetector( onTap: () => node.unfocus(), child: Container( color: Colors.black, padding: EdgeInsets.all(8.0), child: Text( "DONE", style: TextStyle(color: Colors.white), ), ), ); } ], ), KeyboardActionsItem( focusNode: _nodeText6, footerBuilder: (_) => PreferredSize( child: SizedBox( height: 40, child: Center( child: Text('Custom Footer'), )), preferredSize: Size.fromHeight(40)), ), ], ); } @override Widget build(BuildContext context) { return KeyboardActions( config: _buildConfig(context), child: Center( child: Padding( padding: const EdgeInsets.all(15.0), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ TextField( keyboardType: TextInputType.number, focusNode: _nodeText1, decoration: InputDecoration( hintText: "Input Number", ), ), TextField( keyboardType: TextInputType.text, focusNode: _nodeText2, decoration: InputDecoration( hintText: "Input Text with Custom Done Button", ), ), 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 Done button", ), ), TextField( keyboardType: TextInputType.number, focusNode: _nodeText5, decoration: InputDecoration( hintText: "Input Number with Toolbar Buttons", ), ), TextField( keyboardType: TextInputType.number, focusNode: _nodeText6, decoration: InputDecoration( hintText: "Input Number with Custom Footer", ), ), ], ), ), ), ); } } ">
import  'package:flutter/material.dart';
import  'package:keyboard_actions/keyboard_actions.dart';


class Content extends StatefulWidget {
  const Content({
    Key key,
  }) : super(key: key);

  @override
  _ContentState createState() => _ContentState();
}

class _ContentState extends State<Content> {
  final FocusNode _nodeText1 = FocusNode();
  final FocusNode _nodeText2 = FocusNode();
  final FocusNode _nodeText3 = FocusNode();
  final FocusNode _nodeText4 = FocusNode();
  final FocusNode _nodeText5 = FocusNode();
  final FocusNode _nodeText6 = FocusNode();

  /// Creates the [KeyboardActionsConfig] to hook up the fields
  /// and their focus nodes to our [FormKeyboardActions].
  KeyboardActionsConfig _buildConfig(BuildContext context) {
    return KeyboardActionsConfig(
      keyboardActionsPlatform: KeyboardActionsPlatform.ALL,
      keyboardBarColor: Colors.grey[200],
      nextFocus: true,
      actions: [
        KeyboardActionsItem(
          focusNode: _nodeText1,
        ),
        KeyboardActionsItem(focusNode: _nodeText2, toolbarButtons: [
          (node) {
            return GestureDetector(
              onTap: () => node.unfocus(),
              child: Padding(
                padding: EdgeInsets.all(8.0),
                child: Icon(Icons.close),
              ),
            );
          }
        ]),
        KeyboardActionsItem(
          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(),
                      )
                    ],
                  );
                });
          },
        ),
        KeyboardActionsItem(
          focusNode: _nodeText4,
          displayCloseWidget: false,
        ),
          KeyboardActionsItem(
          focusNode: _nodeText5,
          toolbarButtons: [
            //button 1
            (node) {
              return GestureDetector(
                onTap: () => node.unfocus(),
                child: Container(
                  color: Colors.white,
                  padding: EdgeInsets.all(8.0),
                  child: Text(
                    "CLOSE",
                    style: TextStyle(color: Colors.black),
                  ),
                ),
              );
            },
            //button 2
            (node) {
              return GestureDetector(
                onTap: () => node.unfocus(),
                child: Container(
                  color: Colors.black,
                  padding: EdgeInsets.all(8.0),
                  child: Text(
                    "DONE",
                    style: TextStyle(color: Colors.white),
                  ),
                ),
              );
            }
          ],
        ),
        KeyboardActionsItem(
          focusNode: _nodeText6,
          footerBuilder: (_) => PreferredSize(
              child: SizedBox(
                  height: 40,
                  child: Center(
                    child: Text('Custom Footer'),
                  )),
              preferredSize: Size.fromHeight(40)),
        ),
      ],
    );
  }

  @override
  Widget build(BuildContext context) {
    return KeyboardActions(
      config: _buildConfig(context),
      child: Center(
        child: Padding(
          padding: const EdgeInsets.all(15.0),
          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 Done Button",
                ),
              ),
              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 Done button",
                ),
              ),
              TextField(
                keyboardType: TextInputType.number,
                focusNode: _nodeText5,
                decoration: InputDecoration(
                  hintText: "Input Number with Toolbar Buttons",
                ),
              ),
              TextField(
                keyboardType: TextInputType.number,
                focusNode: _nodeText6,
                decoration: InputDecoration(
                  hintText: "Input Number with Custom Footer",
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

Using Custom Keyboard

(Colors.blue); /// Creates the [KeyboardActionsConfig] to hook up the fields /// and their focus nodes to our [FormKeyboardActions]. KeyboardActionsConfig _buildConfig(BuildContext context) { return KeyboardActionsConfig( keyboardActionsPlatform: KeyboardActionsPlatform.ALL, keyboardBarColor: Colors.grey[200], nextFocus: true, actions: [ KeyboardActionsItem( focusNode: _nodeText7, footerBuilder: (_) => CounterKeyboard( notifier: custom1Notifier, ), ), KeyboardActionsItem( focusNode: _nodeText8, footerBuilder: (_) => ColorPickerKeyboard( notifier: custom2Notifier, ), ), ], ); } @override Widget build(BuildContext context) { return KeyboardActions( config: _buildConfig(context), child: Center( child: Container( padding: const EdgeInsets.all(15.0), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ KeyboardCustomInput ( focusNode: _nodeText7, height: 65, notifier: custom1Notifier, builder: (context, val, hasFocus) { return Container( alignment: Alignment.center, color: hasFocus ? Colors.grey[300] : Colors.white, child: Text( val, style: TextStyle(fontSize: 30, fontWeight: FontWeight.bold), ), ); }, ), KeyboardCustomInput ( focusNode: _nodeText8, height: 65, notifier: custom2Notifier, builder: (context, val, hasFocus) { return Container( width: double.maxFinite, color: val ?? Colors.transparent, ); }, ), ], ), ), ), ); } } /// A quick example "keyboard" widget for picking a color. class ColorPickerKeyboard extends StatelessWidget with KeyboardCustomPanelMixin implements PreferredSizeWidget { final ValueNotifier notifier; static const double _kKeyboardHeight = 200; ColorPickerKeyboard({Key key, this.notifier}) : super(key: key); @override Widget build(BuildContext context) { final double rows = 3; final double screenWidth = MediaQuery.of(context).size.width; final int colorsCount = Colors.primaries.length; final int colorsPerRow = (colorsCount / rows).ceil(); final double itemWidth = screenWidth / colorsPerRow; final double itemHeight = _kKeyboardHeight / rows; return Container( height: _kKeyboardHeight, child: Wrap( children: [ for (final color in Colors.primaries) GestureDetector( onTap: () { updateValue(color); }, child: Container( color: color, width: itemWidth, height: itemHeight, ), ) ], ), ); } @override Size get preferredSize => Size.fromHeight(_kKeyboardHeight); } /// A quick example "keyboard" widget for counter value. class CounterKeyboard extends StatelessWidget with KeyboardCustomPanelMixin implements PreferredSizeWidget { final ValueNotifier notifier; CounterKeyboard({Key key, this.notifier}) : super(key: key); @override Size get preferredSize => Size.fromHeight(200); @override Widget build(BuildContext context) { return Container( height: preferredSize.height, child: Row( children: [ Expanded( child: InkWell( onTap: () { int value = int.tryParse(notifier.value) ?? 0; value--; updateValue(value.toString()); }, child: FittedBox( child: Text( "-", style: TextStyle( fontWeight: FontWeight.bold, ), ), ), ), ), Expanded( child: InkWell( onTap: () { int value = int.tryParse(notifier.value) ?? 0; value++; updateValue(value.toString()); }, child: FittedBox( child: Text( "+", style: TextStyle( fontWeight: FontWeight.bold, ), ), ), ), ), ], ), ); } } ">
import  'package:flutter/material.dart';
import  'package:keyboard_actions/keyboard_actions.dart';

class Content extends StatelessWidget {
  final FocusNode _nodeText7 = FocusNode();
  final FocusNode _nodeText8 = FocusNode();
  //This is only for custom keyboards
  final custom1Notifier = ValueNotifier<String>("0");
  final custom2Notifier = ValueNotifier<Color>(Colors.blue);

  /// Creates the [KeyboardActionsConfig] to hook up the fields
  /// and their focus nodes to our [FormKeyboardActions].
  KeyboardActionsConfig _buildConfig(BuildContext context) {
    return KeyboardActionsConfig(
      keyboardActionsPlatform: KeyboardActionsPlatform.ALL,
      keyboardBarColor: Colors.grey[200],
      nextFocus: true,
      actions: [
        KeyboardActionsItem(
          focusNode: _nodeText7,
          footerBuilder: (_) => CounterKeyboard(
            notifier: custom1Notifier,
          ),
        ),
        KeyboardActionsItem(
          focusNode: _nodeText8,
          footerBuilder: (_) => ColorPickerKeyboard(
            notifier: custom2Notifier,
          ),
        ),
      ],
    );
  }

  @override
  Widget build(BuildContext context) {
    return KeyboardActions(
      config: _buildConfig(context),
      child: Center(
        child: Container(
          padding: const EdgeInsets.all(15.0),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: <Widget>[
              KeyboardCustomInput<String>(
                focusNode: _nodeText7,
                height: 65,
                notifier: custom1Notifier,
                builder: (context, val, hasFocus) {
                  return Container(
                    alignment: Alignment.center,
                    color: hasFocus ? Colors.grey[300] : Colors.white,
                    child: Text(
                      val,
                      style:
                          TextStyle(fontSize: 30, fontWeight: FontWeight.bold),
                    ),
                  );
                },
              ),
              KeyboardCustomInput<Color>(
                focusNode: _nodeText8,
                height: 65,
                notifier: custom2Notifier,
                builder: (context, val, hasFocus) {
                  return Container(
                    width: double.maxFinite,
                    color: val ?? Colors.transparent,
                  );
                },
              ),
            ],
          ),
        ),
      ),
    );
  }
}


/// A quick example "keyboard" widget for picking a color.
class ColorPickerKeyboard extends StatelessWidget
    with KeyboardCustomPanelMixin<Color>
    implements PreferredSizeWidget {
  final ValueNotifier<Color> notifier;
  static const double _kKeyboardHeight = 200;

  ColorPickerKeyboard({Key key, this.notifier}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final double rows = 3;
    final double screenWidth = MediaQuery.of(context).size.width;
    final int colorsCount = Colors.primaries.length;
    final int colorsPerRow = (colorsCount / rows).ceil();
    final double itemWidth = screenWidth / colorsPerRow;
    final double itemHeight = _kKeyboardHeight / rows;

    return Container(
      height: _kKeyboardHeight,
      child: Wrap(
        children: <Widget>[
          for (final color in Colors.primaries)
            GestureDetector(
              onTap: () {
                updateValue(color);
              },
              child: Container(
                color: color,
                width: itemWidth,
                height: itemHeight,
              ),
            )
        ],
      ),
    );
  }

  @override
  Size get preferredSize => Size.fromHeight(_kKeyboardHeight);
}

/// A quick example "keyboard" widget for counter value.
class CounterKeyboard extends StatelessWidget
    with KeyboardCustomPanelMixin<String>
    implements PreferredSizeWidget {
  final ValueNotifier<String> notifier;

  CounterKeyboard({Key key, this.notifier}) : super(key: key);

  @override
  Size get preferredSize => Size.fromHeight(200);

  @override
  Widget build(BuildContext context) {
    return Container(
      height: preferredSize.height,
      child: Row(
        children: [
          Expanded(
            child: InkWell(
              onTap: () {
                int value = int.tryParse(notifier.value) ?? 0;
                value--;
                updateValue(value.toString());
              },
              child: FittedBox(
                child: Text(
                  "-",
                  style: TextStyle(
                    fontWeight: FontWeight.bold,
                  ),
                ),
              ),
            ),
          ),
          Expanded(
            child: InkWell(
              onTap: () {
                int value = int.tryParse(notifier.value) ?? 0;
                value++;
                updateValue(value.toString());
              },
              child: FittedBox(
                child: Text(
                  "+",
                  style: TextStyle(
                    fontWeight: FontWeight.bold,
                  ),
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }
}

You can follow me on twitter @diegoveloper

Comments
  • There is an area appear between actions view and keyboard

    There is an area appear between actions view and keyboard

    There is an area appear between actions view and keyboard ios12, device: iphone xr keyboard type: "TextInputType.number"

    addition: iphone 6/7 is ok.

    opened by kgb16 41
  • Option to set overscroll of BottomAreaAvoider needed

    Option to set overscroll of BottomAreaAvoider needed

    I’m using TextFormFields and the validation text is displayed behind the action bar because the bottom of the editable area scrolls even with the top of the action bar. I believe if we could assign a value to the overscroll parameter of the BottomAreaAvoider it would scroll the extra needed to display the validation text.

    53A1F8B3-1783-4047-ABCF-041F40B29AA8

    opened by jwoverland 28
  • BoxConstraints forces an infinite height

    BoxConstraints forces an infinite height

    I try to implement this: https://pub.dev/packages/keyboard_actions

    But I get this error:

    I/flutter (30378): ══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY ╞═════════════════════════════════════════════════════════ I/flutter (30378): The following assertion was thrown during performLayout(): I/flutter (30378): BoxConstraints forces an infinite height. I/flutter (30378): These invalid constraints were provided to RenderPadding's layout() function by the following I/flutter (30378): function, which probably computed the invalid constraints in question: I/flutter (30378): RenderConstrainedBox.performLayout (package:flutter/src/rendering/proxy_box.dart:259:13) I/flutter (30378): The offending constraints were: I/flutter (30378): BoxConstraints(w=360.0, h=Infinity) I/flutter (30378): I/flutter (30378): When the exception was thrown, this was the stack: I/flutter (30378): #0 BoxConstraints.debugAssertIsValid.<anonymous closure>.throwError (package:flutter/src/rendering/box.dart:507:9) I/flutter (30378): #1 BoxConstraints.debugAssertIsValid.<anonymous closure> (package:flutter/src/rendering/box.dart:550:21) I/flutter (30378): #2 BoxConstraints.debugAssertIsValid (package:flutter/src/rendering/box.dart:554:6)

    It occurs when I give FormKeyboardActions() a child, the child is:

    Padding -> Row[Expanded->Theme->TextFormField]

    The FormKeyboardActions() is a child of Dismissible, Dismissible is a child of SizeTransition, which is a child of Column

    opened by hyperpanthera 19
  • action bar hides behind the keyboard when the version upgrades from 3.4.0 to 3.4.1

    action bar hides behind the keyboard when the version upgrades from 3.4.0 to 3.4.1

    here is my sample code body: Container( width: MediaQuery.of(context).size.width, height: MediaQuery.of(context).size.height, decoration: BoxDecoration(color: Color(0xFF000000)), child: SafeArea(child: Consumer(builder: (context, notifier, child) { return SingleChildScrollView( child: Column( children: [ SizedBox( height: 10, ), Container( height: MediaQuery.of(context).size.height * 0.4, child: KeyboardActions( disableScroll: true, config: _statedKeyboardActionsConfig(notifier: notifier), child: Center( child: Stack( alignment: notifier.memeText.getCurrentStackTextAlign(), children: [ notifier.memeText.showStroke() ? Text( "${notifier.memeText.text}", textAlign: notifier.memeText.getCurrentTextAlign(), style: TextStyle( fontSize: notifier.memeText.fontSize, fontFamily: notifier.memeText.font, fontWeight: MMFontsService.getFontWeight(notifier.memeText.fontWeight), fontStyle: MMFontsService.getFontStyle(notifier.memeText.fontStyle), color: HexColor.fromHex(notifier.memeText.color), ), ) : SizedBox(height: 1), TextField( enableInteractiveSelection: false, focusNode: notifier.normalFocusNode, autofocus: notifier.keyboardFocus, textAlign: notifier.memeText.getCurrentTextAlign(), controller: notifier.textEditingController, decoration: InputDecoration( // contentPadding: const EdgeInsets.all(5), border: InputBorder.none, focusedBorder: InputBorder.none, enabledBorder: InputBorder.none, disabledBorder: InputBorder.none, errorBorder: InputBorder.none, ), textInputAction: TextInputAction.newline, maxLines: null, keyboardType: TextInputType.multiline, style: notifier.getTextFieldTextStyle(), ) ], ), ), ), ), KeyboardCustomInput( focusNode: notifier.colorFocusNode, height: 5, notifier: notusedNotifier, builder: (context, val, hasFocus) { return Container( width: double.maxFinite, ); }, ), ], ), ); })), ),

    please help me.

    opened by KevinSu1991 17
  • Cannot open keyboard again when using TapOutsideBehavior.translucentDismiss

    Cannot open keyboard again when using TapOutsideBehavior.translucentDismiss

    Steps to reproduce:

    1. Run the example app
    2. Go to sample 2
    3. Tap on the text field to open keyboard
    4. Tap on the text field again to dismiss keyboard
    5. Tap on the text field again, the keyboard won't pop up
    opened by crizant 16
  • Flutter Web: Prev/Next/Done button from the keyboard appears under the custom prev/next/done button from this package

    Flutter Web: Prev/Next/Done button from the keyboard appears under the custom prev/next/done button from this package

    Hi,

    I tried on flutter web on ios browser (chrome or safari), the prev/next/done button from the keyboard appears under the prev/next/done button from flutter_keyboard_actions.

    opened by nerakatiryrref 15
  • The action bar is not showing on Android

    The action bar is not showing on Android

    Hi, i need help, i'm use the example code but not work on Android, on iOS it's ok.

    My setup: Android 7.0 keyboard_actions: ^3.2.1+1 [✓] Flutter (Channel stable, v1.17.1, on Mac OS X 10.15.2 19C57, locale pt-BR) [✓] Android toolchain - develop for Android devices (Android SDK version 29.0.2) [✓] Xcode - develop for iOS and macOS (Xcode 11.3.1) [✓] Android Studio (version 3.4) [✓] VS Code (version 1.45.1) [✓] Connected device (1 available)

    image

    opened by silviocandido 15
  • displayActionBar: false does not hide the bar above footer builder

    displayActionBar: false does not hide the bar above footer builder

    On iOS, Flutter 17.1

    There is always an additional bar above the footer builder (custom keyboard). See the red box. Does anyone know how to remove it?

    I've tried displayActionBar: false yet it still shows up.

    image

    opened by lzhuor 14
  • Text in TextField scrolls up after opening the keyboard

    Text in TextField scrolls up after opening the keyboard

    Hello, I faced with the following problem after adding your keyboard: when I open the keyboard text in TextField scrolls up and isn't shown until I close the keyboard. Here are the screenshots:

    Before opening of the keyboard:

    Screen Shot 2019-11-25 at 14 17 42

    After opening:

    Screen Shot 2019-11-25 at 14 18 21

    Text in textfield didn't disappear but it only scrolled up that it's not visible now, unfortunately I can't show it. So, here's the way how I implemented keyboard to my widget:

    class InputGoalWidget extends StatefulWidget {
      final bool isValid = true;
    
      final String title;
      final String hint;
      final TextInputType tit;
      final String emoji;
      final TextEditingController controller;
    
      InputGoalWidget({this.title, this.hint, this.emoji, this.controller, this.tit});
    
      @override
      _InputGoalWidgetState createState() => _InputGoalWidgetState();
    }
    
    class _InputGoalWidgetState extends State<InputGoalWidget> with SingleTickerProviderStateMixin {
      AnimationController animationController;
      Animation<double> animation;
      FocusNode _node = FocusNode();
    
      KeyboardActionsConfig _buildConfig(BuildContext context) {
        return KeyboardActionsConfig(
          keyboardActionsPlatform: KeyboardActionsPlatform.ALL,
          keyboardBarColor: Colors.white,
          nextFocus: false,
          actions: [
            KeyboardAction(
              focusNode: _node,
              displayCloseWidget: true,
            ),
          ],
        );
      }
    
      @override
      void initState() {
        super.initState();
        animationController = AnimationController(
          vsync: this,
          duration: Duration(milliseconds: 600),
        )..addListener(() => setState(() {}));
    
        animation = Tween<double>(
          begin: 50.0,
          end: 120.0,
        ).animate(CurvedAnimation(
          parent: animationController,
          curve: Interval(0.8, 1.0, curve: Curves.fastOutSlowIn),
        ));
    
        animationController.forward();
      }
    
      @override
      Widget build(BuildContext context) {
        return buildContainer(context);
      }
    
      Container buildContainer(BuildContext context) {
        return Container(
          margin: EdgeInsets.only(top: 3),
          color: Color(AppColors.white),
          child: Padding(
            padding: const EdgeInsets.only(top: 15, bottom: 10),
            child: Row(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: <Widget>[
                Padding(
                  padding: const EdgeInsets.only(left: 20.0, right: 16),
                  child: Text(
                    widget.emoji,
                    textAlign: TextAlign.justify,
                    style: TextStyle(fontSize: 32),
                  ),
                ),
                Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: <Widget>[
                    Text(widget.title, style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
                    Container(
                      height: MediaQuery.of(context).size.height * 0.06,
                      width: MediaQuery.of(context).size.width * 0.7,
                      child: Center(
                        child: Padding(
                          padding: const EdgeInsets.only(bottom: 0),
                            child: FormKeyboardActions(
                              config: _buildConfig(context),
                              child: TextField(
                                textCapitalization: TextCapitalization.sentences,
                                focusNode: _node,
                                style: TextStyle(
                                  fontSize: 18,
                                  color: Color(AppColors.brandViolet),
                                  fontWeight: FontWeight.w500,
                                ),
                                keyboardType: widget.tit,
                                inputFormatters: widget.tit == TextInputType.number ? [WhitelistingTextInputFormatter.digitsOnly] : null,
                                decoration: InputDecoration(
                                  hintText: widget.hint,
                                  border: InputBorder.none,
                                ),
                                controller: widget.controller,
                              ),
                            ),
                        ),
                      ),
                    )
                  ],
                )
              ],
            ),
          ),
        );
      }
    }
    
    

    And here's the way how this widgets are used in the screen:

     Flexible(
                flex: 1,
                child: ListView(
                  children: <Widget>[
                    _nameWidget,
                    _calorieWidget,
                    _stepsWidget,
                    _waterWidget,
                  ],
                ),
              ),
    
    

    So. _nameWidget, _calorieWidget, _stepsWidget and _waterWidgetare InputGoalWidgets. Why such issue can happen? Thanks in advance for any help!

    opened by SergeiMikhailovskii 14
  • Keyboard not pushing bottom sheet content upwards

    Keyboard not pushing bottom sheet content upwards

    Am using this library inside my modal bottom sheet. However, I noticed that on pop up, the keyboard does not push the content upwards, it just covers the content. How do I fix this because it is inconvenient for users.

    padding: EdgeInsets.only( bottom: MediaQuery.of(context).viewInsets.bottom),

    Using this code inside my container pushes it up actually but it causes an unwanted top white space above the keyboard.

    opened by benkashbase 13
  • Enhance toolbar customization options

    Enhance toolbar customization options

    It would be great to allow fully customizing the whole toolbar and not just the buttons on the right. Few samples:

    left: configureButton | up - down, right: Done left: speedButton1, speedButton2, speedButton3, right: Done left: up - down, center: speedButton , right: Done left: configureButton, right: down, Done left: speedButton1, speedButton2, speedButton3, right: down, Done

    So there could be something like leftButtons, centerButtons and rightButtons or allow building the whole toolbar widget with possibility to add up/down/done -buttons where wanted.

    As available space is limited the up-button is not very important in my opinion (you can easily tap a field in up-direction anyway). In my app I would prefer having down- and done-buttons and possibly some speed buttons in specific fields (to allow e.g. quickly entering a previously used value).

    opened by kinex 13
  • Why Column last widget move?  dialog move delay

    Why Column last widget move? dialog move delay

    import 'package:flutter/material.dart';
    import 'package:keyboard_actions/keyboard_actions.dart';
    
    void main() => runApp(const MyApp());
    
    class MyApp extends StatelessWidget {
      const MyApp({super.key});
    
      @override
      Widget build(BuildContext context) {
        return const MaterialApp(
          title: 'Material App',
          home: TestWidget(),
        );
      }
    }
    
    class TestWidget extends StatelessWidget {
      const TestWidget({super.key});
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: Column(
            children: [
              Expanded(
                child: ListView.builder(
                  itemCount: 100,
                  itemBuilder: (BuildContext context, int index) {
                    return Text("data $index");
                  },
                ),
              ),
              Container(
                padding: const EdgeInsets.all(20),
                height: 80,
                width: double.infinity,
                color: Colors.redAccent,
                child: GestureDetector(
                  onTap: () => showWriteComment2(context),
                  child: const Text("touch me. Why do I move ?"),
                ),
              ),
            ],
          ),
        );
      }
    }
    
    Future showWriteComment2(BuildContext context) async {
      var focusNode = FocusNode();
      focusNode.requestFocus();
      var controller = TextEditingController();
      return showDialog(
          context: context,
          builder: (context) {
            return GestureDetector(
                onTap: () => Navigator.pop(context),
                child: KeyboardActions(
                  // isDialog: true,
                  config: KeyboardActionsConfig(
                      keyboardActionsPlatform: KeyboardActionsPlatform.ALL,
                      actions: [
                        KeyboardActionsItem(
                          focusNode: focusNode,
                          displayActionBar: false,
                        ),
                      ]),
                  child: Column(
                    mainAxisSize: MainAxisSize.min,
                    mainAxisAlignment: MainAxisAlignment.end,
                    children: [
                      Container(
                        padding: const EdgeInsets.all(8),
                        color: Colors.white,
                        child: TextField(
                          controller: controller,
                          cursorColor: Colors.black,
                          decoration: const InputDecoration(
                            hintText: "Can you remove the delay in my popping up?",
                          ),
                          focusNode: focusNode,
                          maxLines: 7,
                        ),
                      ),
                      GestureDetector(
                        onTap: () {
                          Navigator.pop(context);
                        },
                        child: Container(
                          padding: const EdgeInsets.all(8),
                          color: Colors.amber,
                          width: double.infinity,
                          height: 40,
                          child: const Text("send"),
                        ),
                      )
                    ],
                  ),
                ));
          });
    }
    
    
    opened by xxxIxxxx 2
  • [Bug] Ignore small bump animation when custom keyboard appears

    [Bug] Ignore small bump animation when custom keyboard appears

    Looking at the example find a small bug. When custom keyboard appears with upper position, custom keyboard appears upper position when expected. After a moment, it go back to position which is expected.

    sample 1

    https://user-images.githubusercontent.com/27538852/181661026-da8f2795-f731-43b9-ac10-ec53f3fd0c7f.mov

    sample 2

    https://user-images.githubusercontent.com/27538852/181661339-500a4a23-e788-448e-a0ea-549dd423579a.mov

    Is there any way to make custom keyboard comes from bottom area as device keyboard appears.

    This problem happens in both simulator and real devices.

    opened by ostk0069 0
  • Autofocus not working on iOS

    Autofocus not working on iOS

    Steps that I made:

    Click button to the second page My keyboard doesnt appear but focuses on input. Click on the button that leads to the back page. Press again the button leading to the second page

    Expected results:

    My expectation is that every time I enter the page my keyboard and focus will appear on the input.

    Actual results:

    After a few repetitions of the steps mentioned above, the focus remains on the input but the keyboard no longer appears.

    This only happens on Safari on iOS, I also tested it on Chrome ( on iOS ) and Android phones as a result it worked. A strange fact is that the keyboard does not appear even though the focus is visible on the given input.

    Code sample:

    import 'package:flutter/material.dart';
    import 'package:flutter/services.dart';
    import 'package:keyboard_actions/keyboard_actions.dart';
    import 'package:keyboard_actions/keyboard_actions_item.dart';
    
    void main() {
      runApp(const MaterialApp(
        title: 'Navigation Basics',
        home: FirstRoute(),
      ));
    }
    
    class FirstRoute extends StatelessWidget {
      const FirstRoute({super.key});
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: const Text('First Route'),
          ),
          body: Center(
            child: ElevatedButton(
              child: const Text('Open route'),
              onPressed: () {
                Navigator.push(
                  context,
                  MaterialPageRoute(builder: (context) => SecondRoute()),
                );
              },
            ),
          ),
        );
      }
    }
    
    class SecondRoute extends StatefulWidget {
      SecondRoute({super.key});
    
      @override
      State<SecondRoute> createState() => _SecondRouteState();
    }
    
    class _SecondRouteState extends State<SecondRoute> {
      late FocusNode _nodeText1;
      late TextEditingController _controller1;
    
      KeyboardActionsConfig _buildConfig(BuildContext context) {
        return KeyboardActionsConfig(
          keyboardActionsPlatform: KeyboardActionsPlatform.ALL,
          keyboardBarColor: Colors.grey[200],
          nextFocus: false,
          actions: [
            KeyboardActionsItem(
              focusNode: _nodeText1,
            ),
          ],
        );
      }
    
      void initState() {
        super.initState();
        _nodeText1 = FocusNode();
        _controller1 = TextEditingController();
      }
    
      @override
      void dispose() {
        _nodeText1.dispose();
        _controller1.dispose();
        super.dispose();
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: const Text('Second Route'),
          ),
          body: KeyboardActions(
            config: _buildConfig(context),
            child: Container(
                width: double.infinity,
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  crossAxisAlignment: CrossAxisAlignment.center,
                  children: [
                    TextField(
                      autofocus: true,
                      keyboardType: TextInputType.number,
                      focusNode: _nodeText1,
                      controller: _controller1,
                      decoration: InputDecoration(
                        hintText: "Input Number",
                      ),
                    ),
                    ElevatedButton(
                      onPressed: () {
                        Navigator.pop(context);
                      },
                      child: const Text('Go back!'),
                    )
                  ],
                )),
          ),
        );
      }
    }
    
    opened by denddyprod 1
  • When placing KeybaordActions widget inside an overlay, many render errors

    When placing KeybaordActions widget inside an overlay, many render errors

    Without the KeyboardActions widget everything is fine, but as soon as I add it in I get the following errors:

    ======== Exception caught by rendering library =====================================================
    The following assertion was thrown during paint():
    RenderBox was not laid out: RenderDecoratedBox#8e0ed relayoutBoundary=up2
    'package:flutter/src/rendering/box.dart':
    Failed assertion: line 1979 pos 12: 'hasSize'
    
    
    Either the assertion indicates an error in the framework itself, or we should provide substantially more information in this error message to help you determine and fix the underlying cause.
    In either case, please report this assertion by filing a bug on GitHub:
      https://github.com/flutter/flutter/issues/new?template=2_bug.md
    
    The relevant error-causing widget was: 
      Container-[#cf724] Container:file:///...dropdown_button.dart:106:7
    When the exception was thrown, this was the stack: 
    #2      RenderBox.size (package:flutter/src/rendering/box.dart:1979:12)
    #3      RenderDecoratedBox.paint (package:flutter/src/rendering/proxy_box.dart:2162:12)
    #4      RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:2477:7)
    #5      PaintingContext.paintChild (package:flutter/src/rendering/object.dart:187:13)
    #6      RenderProxyBoxMixin.paint (package:flutter/src/rendering/proxy_box.dart:140:15)
    #7      RenderTransform.paint (package:flutter/src/rendering/proxy_box.dart:2419:17)
    #8      RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:2477:7)
    #9      PaintingContext.paintChild (package:flutter/src/rendering/object.dart:187:13)
    #10     RenderBoxContainerDefaultsMixin.defaultPaint (package:flutter/src/rendering/box.dart:2844:15)
    #11     RenderStack.paintStack (package:flutter/src/rendering/stack.dart:611:5)
    #12     RenderStack.paint (package:flutter/src/rendering/stack.dart:627:7)
    #13     RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:2477:7)
    #14     PaintingContext.paintChild (package:flutter/src/rendering/object.dart:187:13)
    #15     _RenderTheatre.paintStack (package:flutter/src/widgets/overlay.dart:786:15)
    #16     _RenderTheatre.paint (package:flutter/src/widgets/overlay.dart:804:7)
    #17     RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:2477:7)
    #18     PaintingContext.paintChild (package:flutter/src/rendering/object.dart:187:13)
    #19     RenderProxyBoxMixin.paint (package:flutter/src/rendering/proxy_box.dart:140:15)
    #20     RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:2477:7)
    #21     PaintingContext.paintChild (package:flutter/src/rendering/object.dart:187:13)
    #22     RenderProxyBoxMixin.paint (package:flutter/src/rendering/proxy_box.dart:140:15)
    #23     RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:2477:7)
    #24     PaintingContext.paintChild (package:flutter/src/rendering/object.dart:187:13)
    #25     RenderProxyBoxMixin.paint (package:flutter/src/rendering/proxy_box.dart:140:15)
    #26     RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:2477:7)
    #27     PaintingContext.paintChild (package:flutter/src/rendering/object.dart:187:13)
    #28     RenderIndexedStack.paintStack (package:flutter/src/rendering/stack.dart:726:13)
    #29     RenderStack.paint (package:flutter/src/rendering/stack.dart:627:7)
    #30     RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:2477:7)
    #31     PaintingContext.paintChild (package:flutter/src/rendering/object.dart:187:13)
    #32     RenderBoxContainerDefaultsMixin.defaultPaint (package:flutter/src/rendering/box.dart:2844:15)
    #33     RenderCustomMultiChildLayoutBox.paint (package:flutter/src/rendering/custom_layout.dart:408:5)
    #34     RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:2477:7)
    #35     PaintingContext.paintChild (package:flutter/src/rendering/object.dart:187:13)
    #36     RenderProxyBoxMixin.paint (package:flutter/src/rendering/proxy_box.dart:140:15)
    #37     _RenderInkFeatures.paint (package:flutter/src/material/material.dart:598:11)
    #38     RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:2477:7)
    #39     PaintingContext.paintChild (package:flutter/src/rendering/object.dart:187:13)
    #40     RenderProxyBoxMixin.paint (package:flutter/src/rendering/proxy_box.dart:140:15)
    #41     PaintingContext.pushLayer (package:flutter/src/rendering/object.dart:387:12)
    #42     RenderPhysicalModel.paint (package:flutter/src/rendering/proxy_box.dart:1951:15)
    #43     RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:2477:7)
    #44     PaintingContext.paintChild (package:flutter/src/rendering/object.dart:187:13)
    #45     RenderProxyBoxMixin.paint (package:flutter/src/rendering/proxy_box.dart:140:15)
    #46     RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:2477:7)
    #47     PaintingContext.paintChild (package:flutter/src/rendering/object.dart:187:13)
    #48     RenderProxyBoxMixin.paint (package:flutter/src/rendering/proxy_box.dart:140:15)
    #49     RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:2477:7)
    #50     PaintingContext._repaintCompositedChild (package:flutter/src/rendering/object.dart:141:11)
    #51     PaintingContext.repaintCompositedChild (package:flutter/src/rendering/object.dart:100:5)
    #52     PipelineOwner.flushPaint (package:flutter/src/rendering/object.dart:995:29)
    #53     RendererBinding.drawFrame (package:flutter/src/rendering/binding.dart:506:19)
    #54     WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:892:13)
    #55     RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:370:5)
    #56     SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1146:15)
    #57     SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1083:9)
    #58     SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:997:5)
    #62     _invoke (dart:ui/hooks.dart:151:10)
    #63     PlatformDispatcher._drawFrame (dart:ui/platform_dispatcher.dart:308:5)
    #64     _drawFrame (dart:ui/hooks.dart:115:31)
    (elided 5 frames from class _AssertionError and dart:async)
    The following RenderObject was being processed when the exception was fired: RenderDecoratedBox#8e0ed relayoutBoundary=up2
    ...  needs compositing
    ...  parentData: <none> (can use size)
    ...  constraints: BoxConstraints(unconstrained)
    ...  size: MISSING
    ...  decoration: BoxDecoration
    ...    boxShadow: BoxShadow(Color(0x1a000000), Offset(0.0, 20.0), 30.0, 0.0), BlurStyle.normal
    ...  configuration: ImageConfiguration(bundle: PlatformAssetBundle#8cf5b(), devicePixelRatio: 3.0, locale: en, textDirection: TextDirection.ltr, platform: iOS)
    RenderObject: RenderDecoratedBox#8e0ed relayoutBoundary=up2
      needs compositing
      parentData: <none> (can use size)
      constraints: BoxConstraints(unconstrained)
      size: MISSING
      decoration: BoxDecoration
        boxShadow: BoxShadow(Color(0x1a000000), Offset(0.0, 20.0), 30.0, 0.0), BlurStyle.normal
      configuration: ImageConfiguration(bundle: PlatformAssetBundle#8cf5b(), devicePixelRatio: 3.0, locale: en, textDirection: TextDirection.ltr, platform: iOS)
    ...  child: RenderClipRRect#34423 relayoutBoundary=up3 NEEDS-PAINT
    ...    needs compositing
    ...    parentData: <none> (can use size)
    ...    constraints: BoxConstraints(unconstrained)
    ...    size: MISSING
    ...    child: RenderBackdropFilter#352ec relayoutBoundary=up4 NEEDS-PAINT
    ...      needs compositing
    ...      parentData: <none> (can use size)
    ...      constraints: BoxConstraints(unconstrained)
    ...      size: MISSING
    ...      child: RenderConstrainedBox#5061e relayoutBoundary=up5 NEEDS-PAINT
    ...        needs compositing
    ...        parentData: <none> (can use size)
    ...        constraints: BoxConstraints(unconstrained)
    ...        size: MISSING
    ...        additionalConstraints: BoxConstraints(w=380.0, 0.0<=h<=Infinity)
    ...        child: RenderDecoratedBox#01691 relayoutBoundary=up6 NEEDS-PAINT
    ...          needs compositing
    ...          parentData: <none> (can use size)
    ...          constraints: BoxConstraints(w=380.0, 0.0<=h<=Infinity)
    ...          size: MISSING
    ...          decoration: BoxDecoration
    ...            color: Color(0xccfafcff)
    ...          configuration: ImageConfiguration(bundle: PlatformAssetBundle#8cf5b(), devicePixelRatio: 3.0, locale: en, textDirection: TextDirection.ltr, platform: iOS)
    ====================================================================================================
    
    opened by mark8044 3
  • Customise arrows icon

    Customise arrows icon

    Hello,

    is there any way to customise arrow buttons icons? I found information about changing colors which is fine, but can't find any info about icons.

    Screenshot 2022-05-23 at 19 42 52
    opened by matszafraniec 1
Owner
Diego Velásquez López
Mobile Software Architect
Diego Velásquez López
Flutter plugin to display a simple numeric keyboard on Android & iOS

numeric_keyboard A simple numeric keyboard widget Installation Add numeric_keyboard: ^1.1.0 in your pubspec.yaml dependencies. And import it: import '

Hugo EXTRAT 16 Sep 27, 2022
A new Flutter widget that add support for AndroidTV app. Using keyboard to control focus node.

flutter_tv_autofocus A new Flutter widget that add support for AndroidTV app. Using keyboard to control focus node. Getting Started Wrap your flutter

SUPERMONKEY 28 Aug 18, 2022
Awesome Notifications add-on plugin to enable push notifications through Firebase Cloud Messaging with all awesome notifications features.

Awesome Notifications FCM Awesome Notifications add-on to send push notifications using FCM (Firebase Cloud Messaging), with all awesome notifications

Rafael Setragni 8 Jan 4, 2023
A plugin that brings native iOS keyboard behavior to Flutter.

iKeyboard A plugin that brings native iOS keyboard behavior to Flutter. Getting Started Just put IKeyboard as MaterialApp ancestor and put IKeyboard.b

Jonny Borges 1 May 4, 2022
A Flutter plugin for IOS and Android providing a simple way to display PDFs.

Pdf Viewer Plugin A Flutter plugin for IOS and Android providing a simple way to display PDFs. Features: Display PDF. Installation First, add pdf_view

Lucas Britto 56 Sep 26, 2022
Easiest way to add support for light and dark theme in your flutter app.

Adaptive Theme Easiest way to add support for light and dark theme in your Flutter app. It allows to manually set light or dark theme and also lets yo

Birju Vachhani 287 Dec 27, 2022
A Flutter package providing an easy way to add floating ribbon to images.

Floating Ribbon A new Flutter package for creating floating ribbons on images. Dependency dependencies: floating_ribbon: any How To Use In order to

101Loop 12 Sep 26, 2022
An easy way to add rounded corner floating app bar in Flutter project.

rounded_floating_app_bar Rounded floating app bar like new google applications has. This package provides an easy way to add rounded corner floating a

Bhavik Makwana 30 Nov 11, 2021
A package provides an easy way to add shimmer effect in Flutter project

flutter_shimmer_widget A package provides an easy way to add shimmer effect in Flutter project Getting Started Animation Example Project There is a ex

Le Anh Tuan 4 Jun 29, 2022
An easy way to add all google ads to your flutter app.

Google Ads An easy way to add all google ads to your flutter app. How to use it Add the google_mobile_ads package using flutter pub add google_mobile_

Yemeni Open Source 4 Sep 27, 2022
The easiest way to create your animated splash screen in a fully customizable way.

Animated Splash Screen Check it out at Pub.Dev Do it your way Assets image Custom Widget Url image IconData Or just change PageTransition and/or Splas

Clean Code 104 Nov 10, 2022
Flutter form fields designed to take much of the burden of form-related coding off the programmer's back — masks, validations, keyboard type, etc.

well_formed Contents Overview Getting Started Demo application References Overview Well-Formed Widget Fields - Well-Formed - is a collection of Flutte

Dartoos 7 Nov 2, 2022
Flutter package to get keyboard height. Can be used to display a sticker/emoji modal with correct height.

flutter_persistent_keyboard_height Flutter package to get keyboard height. The height is persisted during app sessions and keyboard states (you can us

Arshak Aghakaryan 13 Oct 17, 2022
A Flutter package that provides an Emoji Keyboard widget.

Flutter Choose Keyboard A Flutter package that provides an Emoji Keyboard widget. BASED IN: https://github.com/JeffG05/emoji_picker Key Features Flutt

null 1 Oct 22, 2021
Keyboard Store UI Built With Flutter

Flutter UI Day 15 of 100 - Keyboard Store UI Getting Started git clone https://github.com/afifudinn/flutter-keyboard-store cd flutter-keyboard-store f

Afifudin 0 Dec 4, 2021
A custom keyboard UI for flutter

Flutter Custom Keyboard Design Credit: Dribbble

Muhammad Talha Sultan 27 Nov 28, 2022
The definitive landscape virtual keyboard for flutter projects that can't support regular virtual keyboards

VK Flutter Virtual Keyboard The definitive landscape virtual keyboard for flutte

Mohammad Taha Bin Firoz 13 Dec 13, 2022
Mobile secure keyboard to prevent KeyLogger attack and screen capture.

Mobile secure keyboard to prevent KeyLogger attack and screen capture. Screenshots Alphanumeric Numeric Getting started To use this plugin, add flutte

null 20 Dec 22, 2022
Flutter plugin, support android/ios.Support crop, flip, rotate, color martix, mix image, add text. merge multi images.

image_editor The version of readme pub and github may be inconsistent, please refer to github. Use native(objc,kotlin) code to handle image data, it i

FlutterCandies 317 Jan 3, 2023