virtual_keypad v1.1.1
pub.dev GitHub

Custom layouts

A layout is a list of rows, and a row is a list of keys. There is nothing else to it.

Install#

flutter pub add virtual_keypad
import 'package:virtual_keypad/virtual_keypad.dart';

The shape#

VirtualKeypad(
  type: KeyboardType.custom,
  customLayout: [
    [
      VirtualKey.character(text: 'a'),
      VirtualKey.character(text: 'b'),
    ],
    [
      VirtualKey.action(action: KeyAction.backSpace),
      VirtualKey.action(action: KeyAction.done),
    ],
  ],
)

Rows do not have to be the same length. Keys are laid out evenly across the width, so a short row simply gets wider keys.

The two kinds of key#

ConstructorDoes
VirtualKey.character(text: 'a')Inserts text at the cursor
VirtualKey.action(action: ...)Runs a key action such as backspace, enter or done

A character key is not limited to one character. VirtualKey.character(text: '.com') inserts all four, which is how a URL key or a currency shortcut is built.

Labels#

A character key shows the text it inserts, and that is not configurable: what you see is what goes in. Action keys take a label, because an action has no inserted text to show.

VirtualKey.action(action: KeyAction.backSpace, label: 'Del')
VirtualKey.action(action: KeyAction.done, label: 'Pay')

Spanning columns#

[
  VirtualKey.action(action: KeyAction.shift),
  VirtualKey.character(text: ' ', flex: 4),
  VirtualKey.action(action: KeyAction.backSpace),
]

flex is a share of the row, so the space key above is four times the width of the keys either side of it.

A worked example#

A calculator pad, where the operators sit in their own column.

final calculator = [
  [
    VirtualKey.character(text: '7'),
    VirtualKey.character(text: '8'),
    VirtualKey.character(text: '9'),
    VirtualKey.character(text: '/'),
  ],
  [
    VirtualKey.character(text: '4'),
    VirtualKey.character(text: '5'),
    VirtualKey.character(text: '6'),
    VirtualKey.character(text: '*'),
  ],
  [
    VirtualKey.character(text: '1'),
    VirtualKey.character(text: '2'),
    VirtualKey.character(text: '3'),
    VirtualKey.character(text: '-'),
  ],
  [
    VirtualKey.character(text: '0', flex: 2),
    VirtualKey.character(text: '.'),
    VirtualKey.character(text: '+'),
  ],
];

Reacting to keys yourself#

onKeyPressedWithText reports both the key and the text it inserted, which is null for action keys.

VirtualKeypad(
  type: KeyboardType.custom,
  customLayout: calculator,
  onKeyPressedWithText: (key, text) {
    if (text != null) log('inserted $text');
  },
)

The one rule#

customLayout requires type: KeyboardType.custom, and that type requires a layout. Either one alone asserts in debug, so a setup mistake fails loudly rather than rendering an empty keyboard you then have to diagnose.