Numeric and PIN pads
A PIN pad is a custom layout, which means you decide exactly which keys exist and where.
Install#
flutter pub add virtual_keypadimport 'package:virtual_keypad/virtual_keypad.dart';The quickest numeric pad#
If you only want digits, a number field already gets one with no layout work.
TextField(
controller: controller,
keyboardType: TextInputType.number,
)
// with VirtualKeypad(standalone: true) below itA PIN pad you control#
For a lock screen, an OTP box or a checkout, describe the grid yourself. This is the same mechanism ATM and POS flows use.
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: 'OK'),
],
];
VirtualKeypad(
type: KeyboardType.custom,
customLayout: pinLayout,
)customLayout and type: KeyboardType.custom go together. Using one without the other asserts immediately in debug, so the mistake surfaces at once rather than as an empty keyboard.
Making it look like a pad, not a keyboard#
A PIN pad wants big keys and few of them, so theme it rather than accepting keyboard defaults.
VirtualKeypad(
type: KeyboardType.custom,
customLayout: pinLayout,
height: 360,
width: 320,
theme: VirtualKeypadTheme.dark.copyWith(
keyTextSize: 28,
keyBorderRadius: 16,
verticalGap: 10,
horizontalGap: 10,
),
)Confirming each digit#
On a payment terminal a mis-registered digit is expensive, and the screen is often the only feedback the user gets.
VirtualKeypad(
type: KeyboardType.custom,
customLayout: pinLayout,
feedback: KeyFeedback.both,
)Reading the value#
Scope mode gives you the digits without going through a text field, which suits a PIN display made of dots.
final pin = VirtualKeypadController();
pin.addListener(() {
if (pin.text.length == 4) verify(pin.text);
});Wider keys#
A key's flex sets how many columns it spans, so a zero key can span two while the rest span one.
[
VirtualKey.character(text: '0', flex: 2),
VirtualKey.action(action: KeyAction.backSpace),
]