virtual_keypad 0.4.0
virtual_keypad: ^0.4.0 copied to clipboard
A customizable virtual on-screen keyboard for Flutter with TextField integration. Supports multiple layouts, themes, and works on all platforms.
A fully customizable virtual on-screen keyboard for Flutter.
Perfect for kiosk apps, password UIs, and custom input interfaces.
Features #
- πΉ Multiple Layouts - Text, numeric, phone, email, URL, or fully custom
- π Multi-Language - Built-in English, Bengali & French, easily extensible
- π Standalone Mode - Works with any standard Flutter TextField
- π― Standalone Scope - Restrict keyboard to a widget subtree
- π€ Smart TextField - Auto-adapts keyboard layout based on input type
- π¨ Fully Customizable - Light, dark, or fully custom themes
- π± Cross-Platform - Works on iOS, Android, Web, macOS, Windows, Linux
- βοΈ Full Editing - Selection, copy/paste, cursor control
- π Key Preview - Native-style key press popup feedback
- π«₯ Auto-Hide - Animated show/hide on focus change
Installation #
dependencies:
virtual_keypad: ^latest
Quick Start #
Standalone Mode (works with any TextField) #
import 'package:virtual_keypad/virtual_keypad.dart';
void main() {
initializeKeyboardLayouts();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
final controller = TextEditingController();
@override
Widget build(BuildContext context) {
return Column(
children: [
TextField(controller: controller),
VirtualKeypad(standalone: true),
],
);
}
}
Just add
standalone: trueβ no wrapper widgets needed. The keyboard auto-detects focused fields and adapts layout based onkeyboardType.
Scoped Standalone Mode #
Wrap with VirtualKeypadStandaloneScope to restrict the keyboard to a specific subtree (useful in Widgetbook or multi-panel UIs):
VirtualKeypadStandaloneScope(
child: Column(
children: [
TextField(controller: controller),
VirtualKeypad(standalone: true),
],
),
)
Fields outside the scope won't trigger this keyboard.
Scope Mode (full control) #
import 'package:virtual_keypad/virtual_keypad.dart';
void main() {
initializeKeyboardLayouts();
runApp(MyApp());
}
class _MyAppState extends State<MyApp> {
final controller = VirtualKeypadController();
@override
Widget build(BuildContext context) {
return VirtualKeypadScope(
child: Column(
children: [
VirtualKeypadTextField(
controller: controller,
decoration: InputDecoration(labelText: 'Enter text'),
),
VirtualKeypad(),
],
),
);
}
}
Three components work together:
VirtualKeypadScopeβVirtualKeypadTextFieldβVirtualKeypad. Use this mode for selection callbacks, submit handling, and physical keyboard blocking.
Keyboard Types #
VirtualKeypadTextField(
controller: controller,
keyboardType: KeyboardType.emailAddress, // Auto-shows @ and .
)
| Type | Use Case |
|---|---|
text |
General text input (QWERTY) |
emailAddress |
Email fields (QWERTY + @ .) |
url |
URL fields (QWERTY + / : .) |
number |
Numeric input (0-9) |
phone |
Phone dialer |
multiline |
Text areas with newline |
custom |
User-defined layouts |
Custom Layout #
final pinLayout = [
[
VirtualKey.character(text: '1'),
VirtualKey.character(text: '2'),
VirtualKey.character(text: '3'),
],
[
VirtualKey.character(text: '4'),
VirtualKey.character(text: '5'),
VirtualKey.character(text: '6'),
],
[
VirtualKey.character(text: '7'),
VirtualKey.character(text: '8'),
VirtualKey.character(text: '9'),
],
[
VirtualKey.action(action: KeyAction.backSpace),
VirtualKey.character(text: '0'),
VirtualKey.action(action: KeyAction.done, label: 'β'),
],
];
VirtualKeypad(
type: KeyboardType.custom,
customLayout: pinLayout,
)
Theming #
// Built-in themes
VirtualKeypad(theme: VirtualKeypadTheme.light)
VirtualKeypad(theme: VirtualKeypadTheme.dark)
// Custom theme
VirtualKeypad(
theme: VirtualKeypadTheme(
backgroundColor: Colors.grey[900]!,
keyColor: Colors.grey[800]!,
actionKeyColor: Colors.grey[700]!,
keyTextColor: Colors.white,
keyBorderRadius: 12,
),
)
// Modify existing theme
VirtualKeypad(
theme: VirtualKeypadTheme.dark.copyWith(
keyBorderRadius: 12,
keyTextSize: 24,
),
)
| Property | Type | Default | Description |
|---|---|---|---|
backgroundColor |
Color |
#D1D3D9 |
Keyboard background |
keyColor |
Color |
#FFFFFF |
Character key background |
actionKeyColor |
Color |
#ADB3BC |
Action key background |
keyTextColor |
Color |
#1C1C1E |
Text/icon color |
keyTextSize |
double |
22.0 |
Font size |
keyBorderRadius |
double |
6.0 |
Corner radius |
keyShadow |
bool |
true |
Show key shadows |
splashColor |
Color? |
null |
Tap ripple color |
Multi-Language #
initializeKeyboardLayouts(); // Registers English & Bengali
// Switch language
KeyboardLayoutProvider.instance.setLanguage('bn'); // Bengali
KeyboardLayoutProvider.instance.setLanguage('en'); // English
| Code | Language | Layout |
|---|---|---|
en |
English | QWERTY |
bn |
Bengali | বাΰ¦ΰ¦²ΰ¦Ύ |
fr |
French | AZERTY |
Adding a Custom Language #
final spanishLanguage = KeyboardLanguage(
code: 'es',
name: 'Spanish',
nativeName: 'EspaΓ±ol',
textLayouts: KeyboardLayoutSet(
primary: textPrimaryLayout,
secondary: symbolsLayout,
tertiary: moreSymbolsLayout,
),
);
KeyboardLayoutProvider.instance.registerLanguage(spanishLanguage);
KeyboardLayoutProvider.instance.setLanguage('es');
API Reference #
VirtualKeypadTextField #
VirtualKeypadTextField(
controller: controller, // Required
keyboardType: KeyboardType.text, // Layout type
obscureText: false, // Password mode
allowPhysicalKeyboard: false, // Block system keyboard
maxLength: null, // Character limit
maxLines: 1, // Line count (null = unlimited)
onChanged: (value) {}, // Text change callback
onSubmitted: (value) {}, // Submit callback
)
VirtualKeypad #
VirtualKeypad(
standalone: false, // true = works with any TextField
type: null, // Override layout (auto if null)
height: 280, // Keyboard height
theme: VirtualKeypadTheme.light, // Visual theme
hideWhenUnfocused: false, // Auto-hide animation
customLayout: null, // Custom key arrangement
onKeyPressed: (key) {}, // Key press callback
)
VirtualKeypadController #
final controller = VirtualKeypadController();
controller.insertText('Hello'); // Insert at cursor
controller.deleteBackward(); // Delete before cursor
controller.selectAll(); // Select all text
controller.clear(); // Clear all
controller.cursorPosition = 5; // Set cursor position
controller.moveCursorLeft(); // Move cursor
controller.moveCursorRight();
Examples #
Check out the example directory for a complete demo app with 9 screens showcasing all features.
Documentation #
| Guide | Description |
|---|---|
| API Reference | Complete API documentation |
| Custom Layouts | Build custom keyboard layouts |
| Adding Languages | Add new language support |
| Theming | Customize keyboard appearance |
Contributing #
Contributions welcome! See the Contributing Guide.
License #
MIT License - see LICENSE for details.
Made with β€οΈ by Masum