Skip to content

Instantly share code, notes, and snippets.

@dhruvilp
Created July 7, 2020 17:51
Show Gist options
  • Save dhruvilp/b6db98fa154fe947134ea4d76fcaf511 to your computer and use it in GitHub Desktop.
Save dhruvilp/b6db98fa154fe947134ea4d76fcaf511 to your computer and use it in GitHub Desktop.
Flutter Neumorphic Container / Button
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
backgroundColor: Colors.blueGrey.shade200,
scaffoldBackgroundColor: Colors.blueGrey.shade200,
dialogBackgroundColor: Colors.blueGrey.shade200,
),
home: Scaffold(
body: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
NeumorphicContainer(
child: Text(
'Home',
style: TextStyle(fontSize: 20.0, color: Colors.blueGrey[800]),
),
),
],
),
),
),
);
}
}
class NeumorphicContainer extends StatefulWidget {
final Widget child;
final double bevel;
final Offset blurOffset;
final Color color;
NeumorphicContainer({
Key key,
this.child,
this.bevel = 5.0,
this.color,
}) : this.blurOffset = Offset(bevel / 2, bevel / 2),
super(key: key);
@override
_NeumorphicContainerState createState() => _NeumorphicContainerState();
}
class _NeumorphicContainerState extends State<NeumorphicContainer> {
bool _isPressed = false;
void _onPointerDown(PointerDownEvent event) {
setState(() {
_isPressed == true ? _isPressed = false : _isPressed = true;
});
}
@override
Widget build(BuildContext context) {
final color = this.widget.color ?? Theme.of(context).backgroundColor;
return Listener(
onPointerDown: _onPointerDown,
child: AnimatedContainer(
duration: const Duration(milliseconds: 150),
padding: const EdgeInsets.all(15.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(widget.bevel * 10),
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [
_isPressed ? color : color.mix(Colors.black, .1),
_isPressed ? color.mix(Colors.black, .05) : color,
_isPressed ? color.mix(Colors.black, .05) : color,
color.mix(Colors.white, _isPressed ? .2 : .5),
],
stops: [
0.0,
.3,
.6,
1.0,
]),
boxShadow: _isPressed ?
[
BoxShadow(
blurRadius: widget.bevel / 2,
offset: widget.blurOffset,
color: color.mix(Colors.white, .6),
),
BoxShadow(
blurRadius: widget.bevel / 2,
offset: -widget.blurOffset,
color: color.mix(Colors.black, .3),
),
]
: [
BoxShadow(
blurRadius: widget.bevel / 2,
offset: -widget.blurOffset,
color: color.mix(Colors.white, .6),
),
BoxShadow(
blurRadius: widget.bevel / 2,
offset: widget.blurOffset,
color: color.mix(Colors.black, .3),
)
],
),
child: widget.child,
),
);
}
}
extension ColorUtils on Color {
Color mix(Color another, double amount) {
return Color.lerp(this, another, amount);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment