I'm looking to build a custom keyboard that works with all apps. Custom keyboards are now commonplace. I'm wondering if you are able to build a keyboard in Flutter that would work and be accepted by Apple to work inside other apps.
-
Were you able to achieve this?? – hysabone.com Feb 25 '20 at 22:27
-
Answers below are most probably on CustomInputViews, but only in your app, rather than systemwide! Were you able to achieve this? – Asim Roy Mar 15 '20 at 18:32
-
1Yup they are which doesn't really answer the question. – Jon Scalet Sep 07 '20 at 07:20
-
Does this answer your question? [Is it possible to develop mobile keyboard app in flutter](https://stackoverflow.com/questions/49746413/is-it-possible-to-develop-mobile-keyboard-app-in-flutter) – Tazik_S Dec 21 '20 at 21:33
4 Answers
Sorry, there is no way to do that in Flutter. Flutter is a UI-framework and doesn't extend to OS level changes like the system keyboard. But you can do it natively for Android with Kotlin or Java (iOS not included -- the system does not support OS model's change).
I don't think you can build a system-wide keyboard in Flutter since it is a UI framework. I believe you can build one with the respected operating system's development language (Java for Android, Koltin as well - Swift for iOS devices) as it requires certain permissions to actually function as a system-wide keyboard.
You could use Flutter to build the UI itself, but not the whole keyboard. The rest of the keyboard will need to be either Java or Koltin for Android or Swift for iOS.
Lastly, if you just want a keyboard inside your application, you could build it with Flutter and use your app's language to control the input.
If you want to make a global keyboard, I recommend this guide: https://www.androidauthority.com/lets-build-custom-keyboard-android-832362/
If you want to use Flutter for the UI, I would replace the parts of this guide that utilize it's UI and replace it with Flutter.
I wish you luck in your adventures and if you do make a good keyboard, please give me a download link because GBoard is driving me crazy.

- 67
- 8
-
iOS allows for custom system-wide keyboard, https://developer.apple.com/documentation/uikit/keyboards_and_input/creating_a_custom_keyboard . Even if custom keyboard needs to be a native project, this doesn't necessarily mean that it couldn't host Flutter module to handle UI and business logic. – Estus Flask Sep 27 '20 at 19:24
-
In that case yes, you could build one with iOS. I was getting at where Flutter couldn't singlehandedly use the keyboard - it can handle the UI but not the actual keyboard input and such. I'll update my answer. – WillEridian Sep 27 '20 at 19:31
Better to use system keyboard!
You can use keyboard settings, like a number, decimal, text, email etc for input/

- 1,300
- 6
- 12
You Can Refer https://pub.dev/packages/keyboard_actions For Creating Custom Keyboard/ Add Features to Android/iOS in Simple way through Flutter.
Github Link of Project : https://github.com/diegoveloper/flutter_keyboard_actions/tree/master/example
NOTE:
1. You should then run flutter packages upgrade or update your packages in IntelliJ/ Android Studio.
2. You need Dependencies of Flutter as given Below:
dependencies:
keyboard_actions: "^3.1.2"
Some Features of Custom Keyboard in Flutter :
1. Done button for the keyboard (You can customize the button).
2. Move up/down between your Textfields (You can hide for set nextFocus: false
).
3. Keyboard Bar customization.
4. Custom footer widget below keyboard bar
4. Create your own Keyboard in an easy way
4. You can use it for Android, iOS or both platforms.
4. Compatible with Dialog.
USAGE :
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();
final FocusNode _nodeText7 = 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: [
KeyboardAction(
focusNode: _nodeText1,
),
KeyboardAction(
focusNode: _nodeText2,
closeWidget: Padding(
padding: EdgeInsets.all(8.0),
child: Icon(Icons.close),
),
),
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"),
),
),
KeyboardAction(
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 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",
),
),
TextField(
keyboardType: TextInputType.number,
focusNode: _nodeText6,
decoration: InputDecoration(
hintText: "Input Number with Custom Footer",
),
),
],
),
),
),
);
}
}
Using Custom Keyboard :
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: [
KeyboardAction(
focusNode: _nodeText7,
footerBuilder: (_) => CounterKeyboard(
notifier: custom1Notifier,
),
),
KeyboardAction(
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,
),
)
],
),
);
}
Expected Output :


- 545
- 4
- 11