| // Copyright 2014 The Flutter Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| import 'package:flutter/material.dart'; | |
| import 'package:flutter/services.dart'; | |
| void main() { | |
| runApp( | |
| MaterialApp( | |
| title: 'Hardware Key Demo', | |
| home: Scaffold( | |
| appBar: AppBar(title: const Text('Hardware Key Demo')), | |
| body: const Center(child: HardwareKeyboardDemo()), | |
| ), | |
| ), | |
| ); | |
| } | |
| class HardwareKeyboardDemo extends StatefulWidget { | |
| const HardwareKeyboardDemo({super.key}); | |
| @override | |
| State<HardwareKeyboardDemo> createState() => _HardwareKeyboardDemoState(); | |
| } | |
| class _HardwareKeyboardDemoState extends State<HardwareKeyboardDemo> { | |
| final FocusNode _focusNode = FocusNode(); | |
| KeyEvent? _event; | |
| @override | |
| void dispose() { | |
| _focusNode.dispose(); | |
| super.dispose(); | |
| } | |
| KeyEventResult _handleKeyEvent(FocusNode node, KeyEvent event) { | |
| setState(() { | |
| _event = event; | |
| }); | |
| return KeyEventResult.ignored; | |
| } | |
| @override | |
| Widget build(BuildContext context) { | |
| final TextTheme textTheme = Theme.of(context).textTheme; | |
| return Focus( | |
| focusNode: _focusNode, | |
| onKeyEvent: _handleKeyEvent, | |
| autofocus: true, | |
| child: AnimatedBuilder( | |
| animation: _focusNode, | |
| builder: (BuildContext context, Widget? child) { | |
| if (!_focusNode.hasFocus) { | |
| return GestureDetector( | |
| onTap: () { | |
| _focusNode.requestFocus(); | |
| }, | |
| child: Text('Tap to focus', style: textTheme.headlineMedium), | |
| ); | |
| } | |
| if (_event == null) { | |
| return Text('Press a key', style: textTheme.headlineMedium); | |
| } | |
| final List<Widget> dataText = <Widget>[ | |
| Text('${_event.runtimeType}'), | |
| if (_event?.character?.isNotEmpty ?? false) | |
| Text('character produced: "${_event?.character}"'), | |
| ]; | |
| dataText.add(Text('logical: ${_event?.logicalKey}')); | |
| dataText.add(Text('physical: ${_event?.physicalKey}')); | |
| if (_event?.character != null) { | |
| dataText.add(Text('character: ${_event?.character}')); | |
| } | |
| final List<String> pressed = <String>['Pressed:']; | |
| for (final LogicalKeyboardKey key in HardwareKeyboard.instance.logicalKeysPressed) { | |
| pressed.add(key.debugName!); | |
| } | |
| dataText.add(Text(pressed.join(' '))); | |
| return DefaultTextStyle( | |
| style: textTheme.titleMedium!, | |
| child: Column(mainAxisAlignment: MainAxisAlignment.center, children: dataText), | |
| ); | |
| }, | |
| ), | |
| ); | |
| } | |
| } |