Neumorphism in Flutter

Dial

  1. A circle Container the same color as our background
  2. A ClipPath containing a circular Container with a radial gradient for the highlight
  3. A ClipPath containing a circular Container with a radial gradient for the shadow
class CircleInnerShadow extends StatelessWidget {

final Color shadowColor;
final Color backgroundColor;

const CircleInnerShadow(
{Key key, @required this.shadowColor, @required this.backgroundColor})
: super(key: key);

@override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
shape: BoxShape.circle,
gradient: RadialGradient(
colors: [
backgroundColor,
shadowColor,
],
center: AlignmentDirectional(0.05, 0.05),
focal: AlignmentDirectional(0, 0),
radius: 0.5,
focalRadius: 0,
stops: [0.75,
1.0],
),
),
child: Container(
decoration: BoxDecoration(
shape: BoxShape.circle,
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
stops: [0, 0.45],
colors: [backgroundColor.withOpacity(0), backgroundColor])),
),
);
}
}

class ShadowClipper extends CustomClipper<Path> {
@override
bool shouldReclip(covariant CustomClipper<Path> oldClipper) {
return true;
}

@override
Path getClip(Size size) {
Path path = Path();
path.moveTo(0, 0);
path.lineTo(size.width, 0);
path.lineTo(0, size.height);
path.close();
return path;
}
}
ClipPath(
clipper: ShadowClipper(),
child: CircleInnerShadow(
shadowColor: shadowColor,
backgroundColor: backgroundColor,
),
)
Container(
decoration: BoxDecoration(
color: backgroundColor,
shape: BoxShape.circle,
boxShadow: [
BoxShadow(
color: highlightColor,
offset: Offset(-10, -10),
blurRadius: 20,
spreadRadius: 0),
BoxShadow(
color: shadowColor,
offset: Offset(10, 10),
blurRadius: 20,
spreadRadius: 0)
]
))
import 'package:vector_math/vector_math.dart' as vm;class ProgressRing extends StatelessWidget {
final double progress;

const ProgressRing({Key key, @required this.progress}) : super(key: key);

@override
Widget build(BuildContext context) {
return LayoutBuilder(builder: (context, constraints) {
return SizedBox.expand(
child: CustomPaint(
painter: RingPainter(
strokeWidth: constraints.maxWidth * 0.15,
progress: progress)));
});
}
}

class RingPainter extends CustomPainter {
final double strokeWidth;
final double progress;

RingPainter({@required this.strokeWidth, @required this.progress});

@override
void paint(Canvas canvas, Size size) {
final inset = size.width * 0.18;

final rect =
Rect.fromLTRB(inset, inset, size.width - inset, size.height - inset);

canvas.drawArc(
rect,
vm.radians(-90),
vm.radians(360 * progress),
false,
Paint()
..shader = LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
Constants.gradientStart,
Constants.gradientMiddle,
Constants.gradientEnd
]).createShader(rect)
..style = PaintingStyle.stroke
..strokeWidth = strokeWidth
..strokeCap = StrokeCap.round);
}

@override
bool shouldRepaint(RingPainter oldDelegate) {
if (oldDelegate.progress != progress ||
oldDelegate.strokeWidth != strokeWidth) {
return true;
}
return false;
}
}
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(20)),
color: Constants.backgroundColor,
boxShadow: [
BoxShadow(
color: Constants.softHighlightColor,
offset: Offset(-10, -10),
spreadRadius: 0,
blurRadius: 10),
BoxShadow(
color: Constants.softShadowColor,
offset: Offset(10, 10),
spreadRadius: 0,
blurRadius: 10)
]))
iPhone portrait
iPhone landscape
Mobile Web
Desktop Web

--

--

--

Flutter Fan Boy & Android Developer

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

A SIMPLE HANDY GUIDE TO FLASK

Plotly’s AttributeError: module ‘plotly.validators.layout.margin._t’ has no attribute ‘TValidator’

How to Create a Writing Portfolio When You Have Zero Experience

AWS Lambda Functions Essentials

5 Best Websites To Learn Programming For Free

Selenium Grid 4 — Getting Started with the Dynamic Grid

3 Ways to Use Python Functions Step-by-Step

How Developers Can Prepare Their Apps for GDPR Legislation

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Tony Owen

Tony Owen

Flutter Fan Boy & Android Developer

More from Medium

Equitable Package in a flutter

Flutter Stack Weekly — Issue #3

Ultimate Guide on How to hire Flutter developer

Ultimate Guide on How to hire Flutter developer

Fixing BoxDecoration background animation in Flutter