import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; import '../styles.dart'; class OpacityGestureDetector extends StatefulWidget { final String text; const OpacityGestureDetector(this.text, {super.key}); @override State createState() => _OpacityGestureDetectorState(); } class _OpacityGestureDetectorState extends State { bool checked = false; bool animChecked = false; @override void initState() { super.initState(); } @override Widget build(BuildContext context) { return Text( widget.text, style: const TextStyle(color: Styles.themeNavTitleColor, fontWeight: FontWeight.normal), ); } } enum PointerActiveMode { none, hover, active } class ClickableBuilder extends StatefulWidget { final int minActiveDuration; final Widget Function(BuildContext context, PointerActiveMode mode, Widget child) builder; final Widget? child; const ClickableBuilder( {super.key, required this.builder, this.child, this.minActiveDuration = 150}); @override State createState() => _ClickableBuilder(); } class _ClickableBuilder extends State { bool isHover = false; bool isActive = false; bool isPointerDown = false; bool isPersistActive = false; void onMouseEnter(PointerEnterEvent event) { setState(() { isHover = true; }); } void onMouseExit(PointerExitEvent event) { setState(() { isHover = false; }); } void onPointerDown(dynamic _) { isPointerDown = true; setState(() { isActive = true; }); Future.delayed(Duration(milliseconds: widget.minActiveDuration)).then((value) { if (isPointerDown) { isPersistActive = true; } else { setState(() { isActive = false; }); } }); } void onPointerUp(dynamic _) { isPointerDown = false; if (isPersistActive) { isPersistActive = false; setState(() { isActive = false; }); } } @override Widget build(BuildContext context) { var child = widget.child ?? const SizedBox(); Widget innerItem; if (isActive) { innerItem = widget.builder(context, PointerActiveMode.active, child); } else if (isHover) { innerItem = widget.builder(context, PointerActiveMode.hover, child); } else { innerItem = widget.builder(context, PointerActiveMode.none, child); } return Listener( onPointerDown: onPointerDown, onPointerUp: onPointerUp, onPointerCancel: onPointerUp, child: MouseRegion( onEnter: onMouseEnter, onExit: onMouseExit, child: innerItem, ), ); } }