Created
April 18, 2022 20:40
-
-
Save fathidevs/28751f3529d497727946aaea820a9967 to your computer and use it in GitHub Desktop.
3d button
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'package:flutter/material.dart'; | |
void main() => runApp(const MyApp()); | |
class MyApp extends StatelessWidget { | |
const MyApp({Key? key}) : super(key: key); | |
@override | |
Widget build(BuildContext context) { | |
return MaterialApp( | |
home: Scaffold( | |
body: Center( | |
child: CustomButton( | |
label: "Click Me", | |
onPressed: () {}, | |
elevation: 20.0, | |
), | |
), | |
), | |
); | |
} | |
} | |
class CustomButtonStyle { | |
final Color topFaceColor; | |
final Color bodyColor; | |
final BorderRadius borderRadius; | |
final Color labelColor; | |
const CustomButtonStyle( | |
{this.topFaceColor = Colors.white, | |
this.bodyColor = Colors.grey, | |
this.borderRadius = const BorderRadius.all(Radius.circular(0.0)), | |
this.labelColor = Colors.black}); | |
static const defaultColor = CustomButtonStyle(); | |
static const blue = CustomButtonStyle( | |
topFaceColor: Colors.blue, | |
bodyColor: Colors.blueGrey, | |
labelColor: Colors.white); | |
} | |
class CustomButton extends StatefulWidget { | |
final String label; | |
final Duration duration; | |
final CustomButtonStyle style; | |
final VoidCallback onPressed; | |
final double elevation; | |
const CustomButton( | |
{Key? key, | |
required this.label, | |
this.duration = const Duration(milliseconds: 60), | |
this.style = CustomButtonStyle.defaultColor, | |
this.elevation = 20.0, | |
required this.onPressed}) | |
: super(key: key); | |
@override | |
State<CustomButton> createState() => _CustomButtonState(); | |
} | |
class _CustomButtonState extends State<CustomButton> { | |
final double verticalPadd = 18.0; | |
final double horizontalPadd = 18.0; | |
bool isTapped = false; | |
@override | |
Widget build(BuildContext context) { | |
return GestureDetector( | |
onTapUp: (TapUpDetails details) => _tapUp(details), | |
onTapDown: (TapDownDetails details) => _tapDown(details), | |
onTapCancel: () => _tapCancel(), | |
child: Stack( | |
alignment: Alignment.center, | |
children: [_body(), _topFace()], | |
), | |
); | |
} | |
Widget _topFace() { | |
return AnimatedPadding( | |
duration: widget.duration, | |
curve: Curves.ease, | |
padding: EdgeInsets.only(bottom: isTapped ? 0.0 : widget.elevation), | |
child: Container( | |
decoration: BoxDecoration( | |
color: widget.style.topFaceColor, | |
borderRadius: widget.style.borderRadius), | |
child: Padding( | |
padding: EdgeInsets.symmetric( | |
vertical: verticalPadd, horizontal: horizontalPadd), | |
child: LimitedBox( | |
maxWidth: MediaQuery.maybeOf(context)!.size.width * .9, | |
child: Text( | |
widget.label, | |
style: TextStyle(color: widget.style.labelColor), | |
), | |
), | |
), | |
), | |
); | |
} | |
Widget _body() { | |
return Container( | |
decoration: BoxDecoration( | |
color: widget.style.bodyColor, | |
borderRadius: widget.style.borderRadius, | |
), | |
child: Padding( | |
padding: EdgeInsets.symmetric( | |
vertical: verticalPadd, horizontal: horizontalPadd - .1), | |
child: LimitedBox( | |
maxWidth: MediaQuery.maybeOf(context)!.size.width * .9, | |
child: Visibility( | |
visible: false, | |
maintainAnimation: true, | |
maintainSize: true, | |
maintainState: true, | |
child: Text( | |
widget.label, | |
style: TextStyle(color: widget.style.labelColor), | |
), | |
), | |
), | |
), | |
); | |
} | |
void _tapDown(TapDownDetails details) { | |
setState(() { | |
isTapped = true; | |
}); | |
} | |
void _tapCancel() { | |
setState(() { | |
isTapped = false; | |
}); | |
} | |
void _tapUp(TapUpDetails details) { | |
setState(() { | |
isTapped = false; | |
}); | |
widget.onPressed(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment