88 lines
3.2 KiB
Dart
88 lines
3.2 KiB
Dart
import 'package:flutter/material.dart';
|
|
|
|
class HoverReliefWidget extends StatefulWidget {
|
|
final Widget child;
|
|
final VoidCallback? onPressed;
|
|
final BorderRadius borderRadius;
|
|
final double initialElevation;
|
|
final double hoverElevation;
|
|
final double scaleFactor;
|
|
final bool enableHoverEffect; // Pour activer/désactiver l'effet de survol
|
|
final Color initialShadowColor; // Nouveau paramètre
|
|
final Color hoverShadowColor; // Nouveau paramètre
|
|
|
|
const HoverReliefWidget({
|
|
required this.child,
|
|
this.onPressed,
|
|
this.borderRadius = const BorderRadius.all(Radius.circular(15.0)),
|
|
this.initialElevation = 4.0,
|
|
this.hoverElevation = 8.0,
|
|
this.scaleFactor = 1.03, // Légèrement réduit par rapport à l'exemple précédent
|
|
this.enableHoverEffect = true, // Par défaut, l'effet est activé
|
|
this.initialShadowColor = const Color(0x26000000), // Default: Colors.black.withOpacity(0.15)
|
|
this.hoverShadowColor = const Color(0x4D000000), // Default: Colors.black.withOpacity(0.3)
|
|
super.key,
|
|
});
|
|
|
|
@override
|
|
State<HoverReliefWidget> createState() => _HoverReliefWidgetState();
|
|
}
|
|
|
|
class _HoverReliefWidgetState extends State<HoverReliefWidget> {
|
|
bool _isHovering = false;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final bool canHover = widget.enableHoverEffect && widget.onPressed != null;
|
|
|
|
final hoverTransform = Matrix4.identity()..scale(widget.scaleFactor);
|
|
final transform = _isHovering && canHover ? hoverTransform : Matrix4.identity();
|
|
final shadowColor = _isHovering && canHover ? widget.hoverShadowColor : widget.initialShadowColor;
|
|
final elevation = _isHovering && canHover ? widget.hoverElevation : widget.initialElevation;
|
|
|
|
Widget content = AnimatedContainer(
|
|
duration: const Duration(milliseconds: 200),
|
|
transform: transform,
|
|
transformAlignment: Alignment.center,
|
|
child: Material(
|
|
color: Colors.transparent,
|
|
elevation: elevation,
|
|
shadowColor: shadowColor,
|
|
borderRadius: widget.borderRadius,
|
|
clipBehavior: Clip.antiAlias,
|
|
child: widget.child,
|
|
),
|
|
);
|
|
|
|
if (widget.onPressed == null) {
|
|
// Si non cliquable, on retourne juste le contenu avec l'élévation initiale (pas de survol)
|
|
// Ajustement: pour toujours avoir un Material de base même si non cliquable et sans hover.
|
|
return Material(
|
|
color: Colors.transparent,
|
|
elevation: widget.initialElevation, // Utilise l'élévation initiale
|
|
shadowColor: widget.initialShadowColor, // Appliqué ici pour l'état non cliquable
|
|
borderRadius: widget.borderRadius,
|
|
clipBehavior: Clip.antiAlias,
|
|
child: widget.child,
|
|
);
|
|
}
|
|
|
|
return MouseRegion(
|
|
onEnter: (_) {
|
|
if (widget.enableHoverEffect) setState(() => _isHovering = true);
|
|
},
|
|
onExit: (_) {
|
|
if (widget.enableHoverEffect) setState(() => _isHovering = false);
|
|
},
|
|
cursor: SystemMouseCursors.click,
|
|
child: InkWell(
|
|
onTap: widget.onPressed,
|
|
borderRadius: widget.borderRadius,
|
|
hoverColor: Colors.transparent,
|
|
splashColor: Colors.grey.withOpacity(0.2),
|
|
highlightColor: Colors.grey.withOpacity(0.1),
|
|
child: content,
|
|
),
|
|
);
|
|
}
|
|
} |