keyboard_scaffold 1.0.0
keyboard_scaffold: ^1.0.0 copied to clipboard
A Flutter package to handle keyboard shortcuts with ease.
keyboard_scaffold #
A Flutter package that provides an elegant solution for handling keyboard shortcuts in your Flutter applications. keyboard_scaffold makes it easy to define and manage keyboard combinations with a clean, intuitive API.
Features #
- Easy Keyboard Shortcut Management: Define keyboard shortcuts with simple, readable syntax
- Comprehensive Key Support: Includes constants for all common keys (letters, numbers, function keys, navigation keys, modifiers)
- Modifier Key Handling: Built-in support for Ctrl, Alt, Shift, and Meta keys with automatic left/right variant resolution
- Drop-in Replacement:
KeyboardScaffoldis a complete replacement for Flutter'sScaffoldwidget - Key Combination Mapping: Register multiple key combinations with different callbacks
- No Dependencies: Built purely on Flutter's services package
Getting started #
Add keyboard_scaffold to your pubspec.yaml:
dependencies:
keyboard_scaffold: ^1.0.0
Import the package:
import 'package:keyboard_scaffold/keyboard_scaffold.dart';
Usage #
The core of keyboard_scaffold is the KeyboardScaffold widget, which wraps Flutter's standard Scaffold and adds keyboard shortcut handling capabilities. You define your keyboard shortcuts using KeyCombo and KeyMaps classes.
For now only the ctrlKey, altKey, shiftKey, and metaKey modifier keys are supported (You can only create key combinations with these keys).
The packages provides constants for common keys, such as:- Letters: keyA, keyB, ..., keyZ
- Numbers:
key0,key1, ...,key9 - Function Keys:
f1,f2, ...,f12
so that you can easily reference them when defining your key combinations.
Basic Example #
Here's a simple example that increments a counter when Ctrl+A is pressed:
import 'package:flutter/material.dart';
import 'package:keyboard_scaffold/keyboard_scaffold.dart';
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
late final keyCombo = KeyCombo(
modifiers: [ctrlKey],
bindings: {
keyA: _incrementCounter,
},
);
late final keymap = KeyMaps(combos: [keyCombo]);
@override
Widget build(BuildContext context) {
return KeyboardScaffold(
keyMaps: keymap,
appBar: AppBar(title: const Text('Keyboard Shortcut Demo')),
body: Center(
child: Text('Counter: $_counter'),
),
);
}
}
Advanced Example with Multiple Shortcuts #
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
String _lastAction = '';
void _incrementCounter() {
setState(() {
_counter++;
_lastAction = 'Incremented';
});
}
void _decrementCounter() {
setState(() {
_counter--;
_lastAction = 'Decremented';
});
}
void _resetCounter() {
setState(() {
_counter = 0;
_lastAction = 'Reset';
});
}
void _showWarning() {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Warning: Ctrl+W pressed')),
);
}
late final keyCombo1 = KeyCombo(
modifiers: [ctrlKey],
bindings: {
keyA: _incrementCounter,
keyS: _decrementCounter,
keyR: _resetCounter,
keyW: _showWarning,
},
);
late final keyCombo2 = KeyCombo(
modifiers: [ctrlKey, shiftKey],
bindings: {
keyA: () {
setState(() {
_counter += 10;
_lastAction = 'Fast increment';
});
},
},
);
late final keymap = KeyMaps(combos: [keyCombo1, keyCombo2]);
@override
Widget build(BuildContext context) {
return KeyboardScaffold(
keyMaps: keymap,
appBar: AppBar(title: const Text('Advanced Shortcuts')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Counter: $_counter', style: Theme.of(context).textTheme.headlineMedium),
Text('Last Action: $_lastAction'),
const SizedBox(height: 20),
const Text('Shortcuts:'),
const Text('Ctrl+A: Increment'),
const Text('Ctrl+S: Decrement'),
const Text('Ctrl+R: Reset'),
const Text('Ctrl+Shift+A: Fast Increment (+10)'),
const Text('Ctrl+W: Show Warning'),
],
),
),
);
}
}
Function Key Example #
late final functionKeyCombo = KeyCombo(
modifiers: [],
bindings: {
f1: () => _showHelp(),
f2: () => _toggleSettings(),
f5: () => _refresh(),
f11: () => _toggleFullscreen(),
},
);
Navigation Key Example #
late final navigationCombo = KeyCombo(
modifiers: [altKey],
bindings: {
upKey: () => _navigateUp(),
downKey: () => _navigateDown(),
leftKey: () => _navigatePrevious(),
rightKey: () => _navigateNext(),
homeKey: () => _goToHome(),
endKey: () => _goToEnd(),
},
);
API Reference #
KeyboardScaffold #
A widget that wraps Flutter's Scaffold and adds keyboard shortcut handling capabilities.
Properties:
keyMaps: TheKeyMapsinstance containing your keyboard shortcuts- All standard
Scaffoldproperties (appBar, body, floatingActionButton, etc.)
Example:
KeyboardScaffold(
keyMaps: myKeyMaps,
appBar: AppBar(title: Text('My App')),
body: MyBody(),
)
KeyCombo #
Defines a keyboard combination with modifiers and key bindings.
Constructor:
KeyCombo({
List<LogicalKeyboardKey> modifiers = const [],
required Map<LogicalKeyboardKey, KeyCallback> bindings,
})
Parameters:
modifiers: List of modifier keys (ctrlKey, altKey, shiftKey, metaKey)bindings: Map of keys to callback functions
Example:
KeyCombo(
modifiers: [ctrlKey, shiftKey],
bindings: {
keyS: () => _saveFile(),
keyN: () => _createNew(),
},
)
KeyMaps #
Manages multiple keyboard combinations and handles key events.
Constructor:
KeyMaps({required List<KeyCombo> combos})
Example:
final combo1 = KeyCombo(
modifiers: [ctrlKey],
bindings: {
keyA: () => print('Ctrl+A pressed'),
},
);
final combo2 = KeyCombo(
modifiers: [ctrlKey, shiftKey],
bindings: {
keyS: () => print('Ctrl+Shift+S pressed'),
},
);
final combo3 = KeyCombo(
modifiers: [],
bindings: {
f1: () => print('F1 pressed'),
},
);
final keyMaps = KeyMaps(
combos: [combo1, combo2, combo3],
);
Available Key Constants #
The package provides convenient constants for all keys:
Modifier Keys:
ctrlKey,ctrlLeftKey,ctrlRightKeyaltKey,altLeftKey,altRightKeyshiftKey,shiftLeftKey,shiftRightKeymetaKey
Letter Keys:
keyAthroughkeyZ
Number Keys:
key0throughkey9
Function Keys:
f1throughf12
Navigation Keys:
escKey,tabKey,enterKey,backspaceKey,spaceKeyhomeKey,endKey,pageUpKey,pageDownKeyinsKey,delKeyupKey,downKey,leftKey,rightKey
Dynamic Key Function #
For dynamic key generation:
LogicalKeyboardKey key(String char)
Example:
final keyA = key('a'); // Returns LogicalKeyboardKey.keyA
final key5 = key('5'); // Returns LogicalKeyboardKey.digit5
KeyName Utility #
Get human-readable names for keys:
String keyName = KeyName.forKey(keyA); // Returns "A"
String combo = KeyName.forKeys([ctrlKey, keyS]); // Returns "Control+S"
Complete Working Example #
Here's a complete example demonstrating various features:
import 'package:flutter/material.dart';
import 'package:keyboard_scaffold/keyboard_scaffold.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Keyboard Scaffold Demo',
theme: ThemeData(primarySwatch: Colors.blue),
home: const DemoPage(),
);
}
}
class DemoPage extends StatefulWidget {
const DemoPage({super.key});
@override
State<DemoPage> createState() => _DemoPageState();
}
class _DemoPageState extends State<DemoPage> {
int _counter = 0;
String _lastShortcut = 'None';
void _updateCounter(int delta, String shortcut) {
setState(() {
_counter += delta;
_lastShortcut = shortcut;
});
}
late final basicCombo = KeyCombo(
modifiers: [ctrlKey],
bindings: {
keyA: () => _updateCounter(1, 'Ctrl+A'),
keyS: () => _updateCounter(-1, 'Ctrl+S'),
keyR: () {
setState(() {
_counter = 0;
_lastShortcut = 'Ctrl+R (Reset)';
});
},
},
);
late final advancedCombo = KeyCombo(
modifiers: [ctrlKey, shiftKey],
bindings: {
keyA: () => _updateCounter(10, 'Ctrl+Shift+A'),
keyS: () => _updateCounter(-10, 'Ctrl+Shift+S'),
},
);
late final functionCombo = KeyCombo(
modifiers: [],
bindings: {
f1: () {
_showDialog('Help', 'Press Ctrl+A to increment\nPress Ctrl+S to decrement');
},
f5: () {
setState(() {
_counter = 0;
_lastShortcut = 'F5 (Refresh)';
});
},
},
);
late final keyMaps = KeyMaps(combos: [basicCombo, advancedCombo, functionCombo]);
void _showDialog(String title, String message) {
showDialog(
context: context,
builder: (context) => AlertDialog(
title: Text(title),
content: Text(message),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: const Text('OK'),
),
],
),
);
}
@override
Widget build(BuildContext context) {
return KeyboardScaffold(
keyMaps: keyMaps,
appBar: AppBar(
title: const Text('Keyboard Scaffold Demo'),
),
body: Center(
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Counter: $_counter',
style: Theme.of(context).textTheme.displayLarge,
),
const SizedBox(height: 20),
Text(
'Last Shortcut: $_lastShortcut',
style: Theme.of(context).textTheme.titleLarge,
),
const SizedBox(height: 40),
const Divider(),
const SizedBox(height: 20),
const Text(
'Available Shortcuts:',
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
),
const SizedBox(height: 10),
_buildShortcutInfo('Ctrl+A', 'Increment by 1'),
_buildShortcutInfo('Ctrl+S', 'Decrement by 1'),
_buildShortcutInfo('Ctrl+R', 'Reset counter'),
_buildShortcutInfo('Ctrl+Shift+A', 'Increment by 10'),
_buildShortcutInfo('Ctrl+Shift+S', 'Decrement by 10'),
_buildShortcutInfo('F1', 'Show help'),
_buildShortcutInfo('F5', 'Refresh (reset)'),
],
),
),
),
);
}
Widget _buildShortcutInfo(String shortcut, String description) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 4.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
decoration: BoxDecoration(
border: Border.all(color: Colors.grey),
borderRadius: BorderRadius.circular(4),
),
child: Text(
shortcut,
style: const TextStyle(fontFamily: 'monospace'),
),
),
const SizedBox(width: 10),
Text(description),
],
),
);
}
}
Tips and Best Practices #
-
Modifier Key Aliasing: The package automatically handles left/right variants of modifier keys. Using
ctrlKeywill match bothctrlLeftKeyandctrlRightKey. -
Multiple Combos: You can register multiple
KeyComboinstances with the same modifiers but different keys, or different modifiers altogether. -
State Management: Callbacks can access widget state through closures, making it easy to integrate with setState or other state management solutions.
-
Focus Management:
KeyboardScaffoldautomatically manages focus to ensure keyboard events are captured properly. -
Debugging: The package includes print statements for debugging. Look for "KeyMaps:" and "KeyCombo:" prefixes in your console output.
Social Media #
Connect in social media for more information and updates:
-
Instagram: @i_am_utsav__
-
Facebook: utsav.pokhrel.9674
-
TikTok: @i_am_utsav__
If you have any questions or need further assistance, feel free to reach out through any of these channels.
Additional Information #
Contributing #
Contributions are welcome! Please feel free to submit issues or pull requests on our GitHub repository.
Support #
For bugs or feature requests, please file an issue on the GitHub repository.
License #
This package is licensed under the MIT License. See the LICENSE file for details.