| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263 |
- import 'package:flutter/material.dart';
- import 'package:flutter/services.dart';
- /// A lightweight press-scale wrapper used instead of InkWell for the large
- /// dashboard tiles. It keeps touch feedback cheap on older devices.
- class Pressable extends StatefulWidget {
- const Pressable({
- super.key,
- required this.child,
- this.onTap,
- this.onLongPress,
- this.semanticLabel,
- this.pressedScale = 0.965,
- this.borderRadius = BorderRadius.zero,
- });
- final Widget child;
- final VoidCallback? onTap;
- final VoidCallback? onLongPress;
- final String? semanticLabel;
- final double pressedScale;
- final BorderRadius borderRadius;
- @override
- State<Pressable> createState() => _PressableState();
- }
- class _PressableState extends State<Pressable> {
- bool _pressed = false;
- void _setPressed(bool pressed) {
- if (!mounted || _pressed == pressed) return;
- setState(() => _pressed = pressed);
- }
- @override
- Widget build(BuildContext context) {
- final canInteract = widget.onTap != null || widget.onLongPress != null;
- return Semantics(
- button: canInteract,
- label: widget.semanticLabel,
- child: GestureDetector(
- behavior: HitTestBehavior.opaque,
- onTapDown: canInteract ? (_) => _setPressed(true) : null,
- onTapUp: canInteract ? (_) => _setPressed(false) : null,
- onTapCancel: canInteract ? () => _setPressed(false) : null,
- onTap: widget.onTap,
- onLongPress: widget.onLongPress == null
- ? null
- : () {
- HapticFeedback.mediumImpact();
- widget.onLongPress!();
- },
- child: AnimatedScale(
- scale: _pressed ? widget.pressedScale : 1,
- duration: const Duration(milliseconds: 110),
- curve: Curves.easeOutCubic,
- child: widget.child,
- ),
- ),
- );
- }
- }
|