Last active
November 19, 2025 18:06
-
-
Save PlugFox/097c35feb4cc3da7a4bce2d902b3a75b to your computer and use it in GitHub Desktop.
InkyIcon widget
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| * InkyIcon widget. | |
| * https://gist.github.com/PlugFox/097c35feb4cc3da7a4bce2d902b3a75b | |
| * https://dartpad.dev?id=097c35feb4cc3da7a4bce2d902b3a75b | |
| * Mike Matiunin <[email protected]>, 19 November 2025 | |
| */ | |
| import 'package:flutter/material.dart'; | |
| import 'package:flutter/services.dart'; | |
| void main() => runApp( | |
| MaterialApp( | |
| home: Scaffold( | |
| body: SafeArea( | |
| child: Center( | |
| child: DecoratedBox( | |
| decoration: ShapeDecoration( | |
| shape: RoundedRectangleBorder( | |
| borderRadius: BorderRadius.circular(16), | |
| ), | |
| color: Colors.grey.shade200, | |
| ), | |
| child: Padding( | |
| padding: const EdgeInsets.all(8), | |
| child: InkyIcon( | |
| label: 'Inky Icon', | |
| icon: const Icon(Icons.star), | |
| onTap: () => print('Icon tapped'), // ignore: avoid_print | |
| ), | |
| ), | |
| ), | |
| ), | |
| ), | |
| ), | |
| ), | |
| ); | |
| /// {@template ink_icon} | |
| /// InkIcon widget. | |
| /// {@endtemplate} | |
| class InkyIcon extends StatefulWidget { | |
| /// {@macro ink_icon} | |
| const InkyIcon({ | |
| required this.label, | |
| required this.icon, | |
| required this.onTap, | |
| super.key, // ignore: unused_element_parameter | |
| }); | |
| final String label; | |
| final Widget icon; | |
| final VoidCallback onTap; | |
| @override | |
| State<InkyIcon> createState() => _InkyIconState(); | |
| } | |
| /// State for widget InkIcon. | |
| class _InkyIconState extends State<InkyIcon> { | |
| MaterialInkController? _materialInkController; | |
| late ThemeData _theme; | |
| late IconThemeData _iconTheme; | |
| late TextDirection _textDirection; | |
| @override | |
| void didChangeDependencies() { | |
| super.didChangeDependencies(); | |
| _textDirection = Directionality.of(context); | |
| _theme = Theme.of(context); | |
| _iconTheme = _theme.iconTheme.copyWith(size: 32); | |
| } | |
| void _onTap(BuildContext context, Offset position) { | |
| if (!mounted) return; | |
| widget.onTap(); | |
| HapticFeedback.lightImpact().ignore(); | |
| if (_materialInkController case MaterialInkController controller) { | |
| if (context.findRenderObject() case RenderBox referenceBox) { | |
| _theme.splashFactory | |
| .create( | |
| controller: controller, | |
| color: _theme.splashColor, | |
| textDirection: _textDirection, | |
| referenceBox: referenceBox, | |
| position: position, | |
| ) | |
| .confirm(); | |
| } | |
| } | |
| } | |
| @override | |
| Widget build(BuildContext context) => GestureDetector( | |
| behavior: HitTestBehavior.opaque, | |
| onTapDown: (details) => _onTap(context, details.localPosition), | |
| child: Padding( | |
| padding: const EdgeInsets.all(4), | |
| child: SizedBox.square( | |
| dimension: 68, | |
| child: Column( | |
| mainAxisSize: MainAxisSize.max, | |
| mainAxisAlignment: MainAxisAlignment.spaceBetween, | |
| crossAxisAlignment: CrossAxisAlignment.center, | |
| children: <Widget>[ | |
| SizedBox.square( | |
| dimension: 42, | |
| child: Material( | |
| shape: const RoundedRectangleBorder( | |
| borderRadius: BorderRadius.all(Radius.circular(8)), | |
| ), | |
| type: MaterialType.card, | |
| color: _theme.colorScheme.primaryContainer, | |
| elevation: 4, | |
| clipBehavior: Clip.antiAlias, | |
| child: IconTheme( | |
| data: _iconTheme, | |
| child: Center( | |
| child: Builder( | |
| builder: (context) { | |
| _materialInkController = Material.maybeOf(context); | |
| return widget.icon; | |
| }, | |
| ), | |
| ), | |
| ), | |
| ), | |
| ), | |
| Text( | |
| widget.label, | |
| maxLines: 1, | |
| overflow: TextOverflow.ellipsis, | |
| style: _theme.textTheme.bodyMedium, | |
| ), | |
| ], | |
| ), | |
| ), | |
| ), | |
| ); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment