| // 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. |
| |
| // Template: dev/snippets/config/templates/stateful_widget_material.tmpl |
| // |
| // Comment lines marked with "▼▼▼" and "▲▲▲" are used for authoring |
| // of samples, and may be ignored if you are just exploring the sample. |
| |
| // Flutter code sample for FocusableActionDetector |
| // |
| //*************************************************************************** |
| //* ▼▼▼▼▼▼▼▼ description ▼▼▼▼▼▼▼▼ (do not modify or remove section marker) |
| |
| // This example shows how keyboard interaction can be added to a custom control |
| // that changes color when hovered and focused, and can toggle a light when |
| // activated, either by touch or by hitting the `X` key on the keyboard when |
| // the "And Me" button has the keyboard focus (be sure to use TAB to move the |
| // focus to the "And Me" button before trying it out). |
| // |
| // This example defines its own key binding for the `X` key, but in this case, |
| // there is also a default key binding for [ActivateAction] in the default key |
| // bindings created by [WidgetsApp] (the parent for [MaterialApp], and |
| // [CupertinoApp]), so the `ENTER` key will also activate the buttons. |
| |
| //* ▲▲▲▲▲▲▲▲ description ▲▲▲▲▲▲▲▲ (do not modify or remove section marker) |
| //*************************************************************************** |
| |
| import 'package:flutter/material.dart'; |
| //**************************************************************************** |
| //* ▼▼▼▼▼▼▼▼ code-imports ▼▼▼▼▼▼▼▼ (do not modify or remove section marker) |
| |
| import 'package:flutter/services.dart'; |
| |
| //* ▲▲▲▲▲▲▲▲ code-imports ▲▲▲▲▲▲▲▲ (do not modify or remove section marker) |
| //**************************************************************************** |
| |
| void main() => runApp(const MyApp()); |
| |
| /// This is the main application widget. |
| class MyApp extends StatelessWidget { |
| const MyApp({Key? key}) : super(key: key); |
| |
| static const String _title = 'Flutter Code Sample'; |
| |
| @override |
| Widget build(BuildContext context) { |
| return const MaterialApp( |
| title: _title, |
| home: MyStatefulWidget(), |
| ); |
| } |
| } |
| |
| //***************************************************************************** |
| //* ▼▼▼▼▼▼▼▼ code-preamble ▼▼▼▼▼▼▼▼ (do not modify or remove section marker) |
| |
| class FadButton extends StatefulWidget { |
| const FadButton({ |
| Key? key, |
| required this.onPressed, |
| required this.child, |
| }) : super(key: key); |
| |
| final VoidCallback onPressed; |
| final Widget child; |
| |
| @override |
| State<FadButton> createState() => _FadButtonState(); |
| } |
| |
| class _FadButtonState extends State<FadButton> { |
| bool _focused = false; |
| bool _hovering = false; |
| bool _on = false; |
| late final Map<Type, Action<Intent>> _actionMap; |
| final Map<ShortcutActivator, Intent> _shortcutMap = |
| const <ShortcutActivator, Intent>{ |
| SingleActivator(LogicalKeyboardKey.keyX): ActivateIntent(), |
| }; |
| |
| @override |
| void initState() { |
| super.initState(); |
| _actionMap = <Type, Action<Intent>>{ |
| ActivateIntent: CallbackAction<Intent>( |
| onInvoke: (Intent intent) => _toggleState(), |
| ), |
| }; |
| } |
| |
| Color get color { |
| Color baseColor = Colors.lightBlue; |
| if (_focused) { |
| baseColor = Color.alphaBlend(Colors.black.withOpacity(0.25), baseColor); |
| } |
| if (_hovering) { |
| baseColor = Color.alphaBlend(Colors.black.withOpacity(0.1), baseColor); |
| } |
| return baseColor; |
| } |
| |
| void _toggleState() { |
| setState(() { |
| _on = !_on; |
| }); |
| } |
| |
| void _handleFocusHighlight(bool value) { |
| setState(() { |
| _focused = value; |
| }); |
| } |
| |
| void _handleHoveHighlight(bool value) { |
| setState(() { |
| _hovering = value; |
| }); |
| } |
| |
| @override |
| Widget build(BuildContext context) { |
| return GestureDetector( |
| onTap: _toggleState, |
| child: FocusableActionDetector( |
| actions: _actionMap, |
| shortcuts: _shortcutMap, |
| onShowFocusHighlight: _handleFocusHighlight, |
| onShowHoverHighlight: _handleHoveHighlight, |
| child: Row( |
| children: <Widget>[ |
| Container( |
| padding: const EdgeInsets.all(10.0), |
| color: color, |
| child: widget.child, |
| ), |
| Container( |
| width: 30, |
| height: 30, |
| margin: const EdgeInsets.all(10.0), |
| color: _on ? Colors.red : Colors.transparent, |
| ), |
| ], |
| ), |
| ), |
| ); |
| } |
| } |
| |
| //* ▲▲▲▲▲▲▲▲ code-preamble ▲▲▲▲▲▲▲▲ (do not modify or remove section marker) |
| //***************************************************************************** |
| |
| /// This is the stateful widget that the main application instantiates. |
| class MyStatefulWidget extends StatefulWidget { |
| const MyStatefulWidget({Key? key}) : super(key: key); |
| |
| @override |
| State<MyStatefulWidget> createState() => _MyStatefulWidgetState(); |
| } |
| |
| /// This is the private State class that goes with MyStatefulWidget. |
| class _MyStatefulWidgetState extends State<MyStatefulWidget> { |
| //******************************************************************** |
| //* ▼▼▼▼▼▼▼▼ code ▼▼▼▼▼▼▼▼ (do not modify or remove section marker) |
| |
| @override |
| Widget build(BuildContext context) { |
| return Scaffold( |
| appBar: AppBar( |
| title: const Text('FocusableActionDetector Example'), |
| ), |
| body: Center( |
| child: Row( |
| mainAxisAlignment: MainAxisAlignment.center, |
| children: <Widget>[ |
| Padding( |
| padding: const EdgeInsets.all(8.0), |
| child: |
| TextButton(onPressed: () {}, child: const Text('Press Me')), |
| ), |
| Padding( |
| padding: const EdgeInsets.all(8.0), |
| child: FadButton(onPressed: () {}, child: const Text('And Me')), |
| ), |
| ], |
| ), |
| ), |
| ); |
| } |
| |
| //* ▲▲▲▲▲▲▲▲ code ▲▲▲▲▲▲▲▲ (do not modify or remove section marker) |
| //******************************************************************** |
| |
| } |