virtual_keypad 0.5.1
virtual_keypad: ^0.5.1 copied to clipboard
A customizable virtual on-screen keyboard for Flutter. 12 built-in languages with RTL support. Text, numeric, phone, email, and URL layouts with full theming.
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 - 12 built-in languages, 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
Supported Languages #
All 12 languages are registered automatically when you call initializeKeyboardLayouts().
| Code | Language | Native Name | Layout | Script | RTL |
|---|---|---|---|---|---|
ar |
Arabic | العربية | Arabic IBM PC | Arabic | ✅ |
bn |
Bengali | বাংলা | Bengali | Bengali | |
de |
German | Deutsch | QWERTZ | Latin | |
en |
English | English | QWERTY | Latin | |
es |
Spanish | Español | QWERTY (ES) | Latin | |
fr |
French | Français | AZERTY | Latin | |
hi |
Hindi | हिन्दी | Devanagari | Devanagari | |
ko |
Korean | 한국어 | Dubeolsik (두벌식) | Hangul | |
pt |
Portuguese | Português | QWERTY (PT) | Latin | |
ru |
Russian | Русский | ЙЦУКЕН (JCUKEN) | Cyrillic | |
th |
Thai | ไทย | Kedmanee | Thai | |
tr |
Turkish | Türkçe | QWERTY (TR) | Latin |
Note: If you notice any incorrect characters, missing keys, or layout mismatches for a language you are fluent in, feel free to fix it and create a pull request. Community contributions are welcome!
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 all 12 languages
// Switch language
KeyboardLayoutProvider.instance.setLanguage('ar'); // Arabic
KeyboardLayoutProvider.instance.setLanguage('ko'); // Korean
KeyboardLayoutProvider.instance.setLanguage('en'); // English
Adding a Custom Language #
final myLanguage = KeyboardLanguage(
code: 'xx',
name: 'MyLanguage',
nativeName: 'MyLanguage',
textLayouts: KeyboardLayoutSet(
primary: textPrimaryLayout,
secondary: symbolsLayout,
tertiary: moreSymbolsLayout,
),
);
KeyboardLayoutProvider.instance.registerLanguage(myLanguage);
KeyboardLayoutProvider.instance.setLanguage('xx');
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