Skip to content

Instantly share code, notes, and snippets.

@taheri79
Last active August 11, 2024 08:59
Show Gist options
  • Save taheri79/d6ab31847fa9dbd91ed56e5ad1b585e4 to your computer and use it in GitHub Desktop.
Save taheri79/d6ab31847fa9dbd91ed56e5ad1b585e4 to your computer and use it in GitHub Desktop.
Flutter Fancy Button
import 'package:flutter/material.dart';
class FancyButton extends StatefulWidget {
const FancyButton({
Key? key,
required this.child,
required this.size,
required this.color,
this.duration = const Duration(milliseconds: 160),
this.onPressed,
}) : super(key: key);
final Widget child;
final Color color;
final Duration duration;
final VoidCallback? onPressed;
final double size;
@override
_FancyButtonState createState() => _FancyButtonState();
}
class _FancyButtonState extends State<FancyButton> with TickerProviderStateMixin {
AnimationController? _animationController;
Animation<double>? _pressedAnimation;
TickerFuture? _downTicker;
double get buttonDepth => widget.size * 0.2;
@override
void initState() {
super.initState();
_setupAnimation();
}
void _setupAnimation() {
_animationController?.stop();
final oldControllerValue = _animationController?.value ?? 0;
_animationController?.dispose();
_animationController = AnimationController(
duration: Duration(microseconds: widget.duration.inMicroseconds ~/ 2),
vsync: this,
value: oldControllerValue,
);
_pressedAnimation = Tween<double>(begin: -buttonDepth, end: 0.0).animate(
CurvedAnimation(parent: _animationController!, curve: Curves.easeInOut),
);
}
@override
void didUpdateWidget(FancyButton oldWidget) {
super.didUpdateWidget(oldWidget);
if (oldWidget.duration != widget.duration) {
_setupAnimation();
}
}
@override
void dispose() {
_animationController?.dispose();
super.dispose();
}
void _onTapDown(TapDownDetails _) {
if (widget.onPressed != null) {
_downTicker = _animationController?.animateTo(1.0);
}
}
void _onTapUp(TapUpDetails _) {
if (widget.onPressed != null) {
_downTicker?.whenComplete(() {
_animationController?.animateTo(0.0);
widget.onPressed?.call();
});
}
}
void _onTapCancel() {
if (widget.onPressed != null) {
_animationController?.reset();
}
}
@override
Widget build(BuildContext context) {
final vertPadding = widget.size * 0.25;
final horzPadding = widget.size * 0.50;
final radius = BorderRadius.circular(horzPadding * 0.5);
return Container(
padding: widget.onPressed != null ? EdgeInsets.only(bottom: 2, left: 0.5, right: 0.5) : null,
decoration: BoxDecoration(
color: Colors.black87,
borderRadius: radius,
),
width: double.infinity,
child: GestureDetector(
onTapDown: _onTapDown,
onTapUp: _onTapUp,
onTapCancel: _onTapCancel,
child: IntrinsicWidth(
child: IntrinsicHeight(
child: Stack(
children: <Widget>[
Container(
decoration: BoxDecoration(
color: _hslRelativeColor(s: -0.20, l: -0.20),
borderRadius: radius,
),
),
_pressedAnimation != null ? AnimatedBuilder(
animation: _pressedAnimation!,
builder: (BuildContext context, Widget? child) {
return Transform.translate(
offset: Offset(0.0, _pressedAnimation!.value),
child: child,
);
},
child: Stack(
clipBehavior: Clip.none, // Updated from Overflow.visible
children: <Widget>[
ClipRRect(
borderRadius: radius,
child: Stack(
children: <Widget>[
DecoratedBox(
decoration: BoxDecoration(
color: _hslRelativeColor(l: 0.06),
borderRadius: radius,
),
child: SizedBox.expand(),
),
Transform.translate(
offset: Offset(0.0, vertPadding * 2),
child: DecoratedBox(
decoration: BoxDecoration(
color: _hslRelativeColor(),
borderRadius: radius,
),
child: SizedBox.expand(),
),
),
],
),
),
Padding(
padding: EdgeInsets.symmetric(
vertical: vertPadding,
horizontal: horzPadding,
),
child: Center(
child: widget.child,
),
)
],
),
) : SizedBox(),
],
),
),
),
),
);
}
Color _hslRelativeColor({double h = 0.0, double s = 0.0, double l = 0.0}) {
final hslColor = HSLColor.fromColor(widget.color);
h = (hslColor.hue + h).clamp(0.0, 360.0);
s = (hslColor.saturation + s).clamp(0.0, 1.0);
l = (hslColor.lightness + l).clamp(0.0, 1.0);
return HSLColor.fromAHSL(hslColor.alpha, h, s, l).toColor();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment