304 lines
11 KiB
Dart
304 lines
11 KiB
Dart
import 'package:flutter/material.dart';
|
|
|
|
enum PredefinedThemes {
|
|
success,
|
|
successOutline,
|
|
danger,
|
|
dangerOutline,
|
|
warning,
|
|
warningOutline,
|
|
info,
|
|
infoOutline,
|
|
primary,
|
|
primaryOutline,
|
|
secondary,
|
|
secondaryOutline,
|
|
dark,
|
|
darkOutline,
|
|
light,
|
|
}
|
|
|
|
List definedColors = [
|
|
// success
|
|
{"color": Color(0xFF5CB85C), "borderColor": Colors.black, "shadowColor": Colors.black, "blurColor": Colors.black},
|
|
// successOutline
|
|
{"color": Color(0xFFFAFAFA), "borderColor": Color(0xFF5CB85C), "shadowColor": Color(0xFF5CB85C), "blurColor": Color(0xFF5CB85C)},
|
|
// danger
|
|
{"color": Color(0xFFD9534F), "borderColor": Colors.black, "shadowColor": Colors.black, "blurColor": Colors.black},
|
|
// dangerOutline
|
|
{"color": Color(0xFFFAFAFA), "borderColor": Color(0xFFD9534F), "shadowColor": Color(0xFFD9534F), "blurColor": Color(0xFFD9534F)},
|
|
// warning
|
|
{"color": Color(0xFFF0AD4E), "borderColor": Colors.black, "shadowColor": Colors.black, "blurColor": Colors.black},
|
|
// warningOutline
|
|
{"color": Color(0xFFFAFAFA), "borderColor": Color(0xFFF0AD4E), "shadowColor": Color(0xFFF0AD4E), "blurColor": Color(0xFFF0AD4E)},
|
|
// info
|
|
{"color": Color(0xFF5BC0DE), "borderColor": Colors.black, "shadowColor": Colors.black, "blurColor": Colors.black},
|
|
// infoOutline
|
|
{"color": Color(0xFFFAFAFA), "borderColor": Color(0xFF5BC0DE), "shadowColor": Color(0xFF5BC0DE), "blurColor": Color(0xFF5BC0DE)},
|
|
// primary
|
|
{"color": Color(0xFF0275D8), "borderColor": Colors.black, "shadowColor": Colors.black, "blurColor": Colors.black},
|
|
// primaryOutline
|
|
{"color": Color(0xFFFAFAFA), "borderColor": Color(0xFF0275D8), "shadowColor": Color(0xFF0275D8), "blurColor": Color(0xFF0275D8)},
|
|
// secondary
|
|
{"color": Color(0xFF6B5B95), "borderColor": Colors.black, "shadowColor": Colors.black, "blurColor": Colors.black},
|
|
// secondaryOutline
|
|
{"color": Color(0xFFFAFAFA), "borderColor": Color(0xFF6B5B95), "shadowColor": Color(0xFF6B5B95), "blurColor": Color(0xFF6B5B95)},
|
|
// dark
|
|
{"color": Color(0xFF292B2C), "borderColor": Colors.black, "shadowColor": Colors.black, "blurColor": Colors.black},
|
|
// darkOutline
|
|
{"color": Color(0xFFFAFAFA), "borderColor": Color(0xFF292B2C), "shadowColor": Color(0xFF292B2C), "blurColor": Color(0xFF292B2C)},
|
|
{"color": Color(0xFFF7F7F7), "borderColor": Colors.black, "shadowColor": Colors.black, "blurColor": Colors.black},
|
|
{"color": Color(0xFFBFBFC4), "borderColor": Colors.black, "shadowColor": Colors.black, "blurColor": Colors.black}
|
|
];
|
|
|
|
class AnimatedButton extends StatefulWidget {
|
|
// * @param onTap The function that is called whenever the widget is tapped
|
|
final GestureTapCallback onTap;
|
|
final Widget child;
|
|
// * @param type There are 16 predefined themes from which you can choose from if you dont want to customize the widget yourself
|
|
final PredefinedThemes type;
|
|
// * @param animationCurve The curve that the animation will follow
|
|
final Curve animationCurve;
|
|
// * @param enabled To check whether the button is enabbled or not
|
|
final bool enabled;
|
|
// * @param isMultiColor To check whether the button has multiple color gradient or not
|
|
final bool isMultiColor;
|
|
// * @param isOutline To check whether the button has a outline or not
|
|
final bool isOutline;
|
|
// * @param darkShadow To check whether the button has dark or light shadow
|
|
final bool darkShadow;
|
|
|
|
// * @param duration The time that the animation takes in milliseconds
|
|
final int duration;
|
|
|
|
// * @param height The height of the widget
|
|
final double height;
|
|
// * @param width The width of the widget
|
|
final double width;
|
|
// * @param blurRadius The radius of the blur effect of the widget
|
|
final double blurRadius;
|
|
// * @param borderRadius The radius of the borders of the widget
|
|
final double borderRadius;
|
|
// * @param shadowHeightBottom The height of the shadow and the animation of the widget from the bottom of the child widget
|
|
final double shadowHeightBottom;
|
|
// * @param shadowHeightLeft The height of the shadow and the animation of the widget from the left of the child widget
|
|
final double shadowHeightLeft;
|
|
// * @param borderWidth The width of the border of the widget
|
|
final double borderWidth;
|
|
|
|
// * @param borderColor The color of the border of the widget(if type is not null, this will not work, is Outline should be true for this to work)
|
|
final Color borderColor;
|
|
// * @param blurColor The color of the blur of the widget(if type is not null, this will not work)
|
|
final Color blurColor;
|
|
// * @param color The color of the widget(if type is not null, this will not work)
|
|
final Color color;
|
|
// * @param shadowColor The color of the shadow of the widget(if type is not null, this will not work)
|
|
final Color? shadowColor;
|
|
|
|
// * @param colors The list of colors for the gradient for the background of the widget(isMulticolor should be true for this to work)
|
|
final List<Color>? colors;
|
|
|
|
AnimatedButton({
|
|
Key? key,
|
|
required this.onTap,
|
|
required this.child,
|
|
this.enabled = true,
|
|
this.type = PredefinedThemes.primary,
|
|
this.color = Colors.blue,
|
|
this.height = 64,
|
|
this.colors,
|
|
this.isMultiColor = false,
|
|
this.darkShadow = true,
|
|
this.width = 200,
|
|
this.duration = 70,
|
|
this.blurRadius = 0,
|
|
this.borderRadius = 12,
|
|
this.animationCurve = Curves.easeIn,
|
|
this.shadowHeightBottom = 4,
|
|
this.shadowHeightLeft = 0,
|
|
this.isOutline = false,
|
|
this.borderColor = Colors.black,
|
|
this.borderWidth = 1,
|
|
this.blurColor = Colors.black,
|
|
this.shadowColor,
|
|
}) : super(key: key);
|
|
|
|
@override
|
|
_AnimatedButtonState createState() => _AnimatedButtonState(
|
|
type: this.type,
|
|
color: this.color,
|
|
blurColor: this.blurColor,
|
|
borderColor: this.borderColor,
|
|
);
|
|
}
|
|
|
|
class _AnimatedButtonState extends State<AnimatedButton> {
|
|
late double btnPositionBottom;
|
|
late double btnPositionTop;
|
|
late double btnPositionLeft;
|
|
late double btnPositionRight;
|
|
PredefinedThemes? type;
|
|
Color? color;
|
|
Color? shadowColor;
|
|
Color? borderColor;
|
|
Color? blurColor;
|
|
_AnimatedButtonState({
|
|
this.type,
|
|
this.color,
|
|
this.shadowColor,
|
|
this.borderColor,
|
|
this.blurColor,
|
|
});
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
// check if there is a PredefinedThemes type used in the widget
|
|
// if yes, over-ride all the colors of the widget
|
|
if (type != null) {
|
|
int index = type!.index;
|
|
setState(() {
|
|
color = definedColors[index]["color"];
|
|
shadowColor = definedColors[index]["shadowColor"];
|
|
blurColor = definedColors[index]["blurColor"];
|
|
borderColor = definedColors[index]["borderColor"];
|
|
});
|
|
} else {
|
|
setState(() {
|
|
color = widget.color;
|
|
shadowColor = widget.shadowColor;
|
|
blurColor = widget.blurColor;
|
|
borderColor = widget.borderColor;
|
|
});
|
|
}
|
|
// initialize the top widget with the defined bottom and left height
|
|
setState(() {
|
|
btnPositionBottom = widget.shadowHeightBottom;
|
|
btnPositionLeft = widget.shadowHeightLeft;
|
|
});
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final double height = widget.height - btnPositionBottom;
|
|
|
|
return GestureDetector(
|
|
child: Center(
|
|
child: Container(
|
|
width: widget.width + btnPositionLeft,
|
|
height: height + btnPositionBottom,
|
|
child: Stack(
|
|
children: <Widget>[
|
|
Positioned(
|
|
bottom: 0,
|
|
child: Container(
|
|
height: height,
|
|
width: widget.width,
|
|
decoration: BoxDecoration(
|
|
gradient: widget.isMultiColor
|
|
? LinearGradient(
|
|
colors: shadow(widget.colors!, widget.darkShadow),
|
|
)
|
|
: null,
|
|
color: (widget.shadowColor != null)
|
|
? widget.shadowColor
|
|
: shadow((widget.isOutline) ? [color!] : [borderColor!], widget.darkShadow),
|
|
borderRadius: BorderRadius.all(
|
|
Radius.circular(
|
|
widget.borderRadius,
|
|
),
|
|
),
|
|
border: widget.isOutline
|
|
? Border.all(
|
|
color: borderColor!,
|
|
width: widget.borderWidth,
|
|
)
|
|
: null,
|
|
boxShadow: <BoxShadow>[
|
|
BoxShadow(
|
|
color: blurColor!,
|
|
blurRadius: widget.blurRadius,
|
|
offset: Offset(0.0, 0.0),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
AnimatedPositioned(
|
|
curve: widget.animationCurve,
|
|
duration: Duration(milliseconds: widget.duration),
|
|
bottom: btnPositionBottom,
|
|
left: btnPositionLeft,
|
|
child: Container(
|
|
height: height,
|
|
width: widget.width,
|
|
decoration: BoxDecoration(
|
|
gradient: widget.isMultiColor
|
|
? LinearGradient(
|
|
colors: widget.colors!,
|
|
)
|
|
: null,
|
|
color: color,
|
|
borderRadius: BorderRadius.all(
|
|
Radius.circular(
|
|
widget.borderRadius,
|
|
),
|
|
),
|
|
border: widget.isOutline
|
|
? Border.all(
|
|
color: borderColor!,
|
|
width: widget.borderWidth,
|
|
)
|
|
: null,
|
|
),
|
|
child: Center(
|
|
child: widget.child,
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
onTapDown: widget.enabled ? _tapDown : null,
|
|
onTapUp: widget.enabled ? _tapUp : null,
|
|
onTapCancel: widget.enabled ? _unTap : null,
|
|
);
|
|
}
|
|
|
|
void _tapDown(_) {
|
|
// when the widget is pressed make both the heights, bottom and left to zero
|
|
setState(() {
|
|
btnPositionBottom = 0;
|
|
btnPositionLeft = 0;
|
|
});
|
|
}
|
|
|
|
// when the widget is released after being pressed, it returns to the given heights, bottom and left
|
|
void _tapUp(_) => _unTap();
|
|
|
|
void _unTap() {
|
|
setState(() {
|
|
btnPositionLeft = widget.shadowHeightLeft;
|
|
|
|
btnPositionBottom = widget.shadowHeightBottom;
|
|
});
|
|
widget.onTap();
|
|
}
|
|
|
|
// returns a list of color shades according to the params
|
|
// * @param colors list of colors
|
|
// * @param darkshadow whether to return a darker shadow or lighter shadow
|
|
shadow(List<Color> colors, bool darkShadow) {
|
|
List<Color> w = [];
|
|
|
|
colors.forEach((color) {
|
|
double amount = darkShadow ? 0.22 : 0.1;
|
|
final hsl = HSLColor.fromColor(color);
|
|
final hslDark = hsl.withLightness((hsl.lightness - amount).clamp(0.0, 1.0));
|
|
w.add(hslDark.toColor());
|
|
});
|
|
return (w.length == 1) ? w[0] : w;
|
|
}
|
|
}
|