2024-03-28 16:25:49 +01:00
|
|
|
import 'package:flutter/material.dart';
|
2024-04-04 19:03:41 +02:00
|
|
|
import 'package:fooder/components/blur_container.dart';
|
2024-03-29 16:47:25 +01:00
|
|
|
|
|
|
|
class ClipShadowPath extends StatelessWidget {
|
|
|
|
final Shadow shadow;
|
|
|
|
final CustomClipper<Path> clipper;
|
|
|
|
final Widget child;
|
|
|
|
|
2024-03-30 14:07:10 +01:00
|
|
|
const ClipShadowPath({
|
|
|
|
super.key,
|
2024-03-29 16:47:25 +01:00
|
|
|
required this.shadow,
|
|
|
|
required this.clipper,
|
|
|
|
required this.child,
|
|
|
|
});
|
|
|
|
|
|
|
|
@override
|
|
|
|
Widget build(BuildContext context) {
|
|
|
|
return CustomPaint(
|
|
|
|
painter: _ClipShadowShadowPainter(
|
2024-03-30 14:07:10 +01:00
|
|
|
clipper: clipper,
|
|
|
|
shadow: shadow,
|
2024-03-29 16:47:25 +01:00
|
|
|
),
|
2024-03-30 14:07:10 +01:00
|
|
|
child: ClipPath(clipper: clipper, child: child),
|
2024-03-29 16:47:25 +01:00
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class _ClipShadowShadowPainter extends CustomPainter {
|
|
|
|
final Shadow shadow;
|
|
|
|
final CustomClipper<Path> clipper;
|
|
|
|
|
|
|
|
_ClipShadowShadowPainter({required this.shadow, required this.clipper});
|
|
|
|
|
|
|
|
@override
|
|
|
|
void paint(Canvas canvas, Size size) {
|
|
|
|
var paint = shadow.toPaint();
|
|
|
|
var clipPath = clipper.getClip(size).shift(shadow.offset);
|
|
|
|
canvas.drawPath(clipPath, paint);
|
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
bool shouldRepaint(CustomPainter oldDelegate) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
2024-03-28 16:25:49 +01:00
|
|
|
|
|
|
|
class BackgroundWave extends StatelessWidget {
|
|
|
|
final double height;
|
|
|
|
|
2024-03-30 14:07:10 +01:00
|
|
|
const BackgroundWave({super.key, required this.height});
|
2024-03-28 16:25:49 +01:00
|
|
|
|
|
|
|
@override
|
|
|
|
Widget build(BuildContext context) {
|
|
|
|
var theme = Theme.of(context);
|
|
|
|
var colorScheme = theme.colorScheme;
|
|
|
|
|
|
|
|
return SizedBox(
|
|
|
|
height: height,
|
2024-04-04 19:03:41 +02:00
|
|
|
child: ClipPath(
|
2024-03-29 16:47:25 +01:00
|
|
|
clipper: BackgroundWaveClipper(),
|
2024-04-04 19:03:41 +02:00
|
|
|
child: BlurContainer(
|
|
|
|
width: MediaQuery.of(context).size.width,
|
|
|
|
height: height,
|
2024-03-29 16:47:25 +01:00
|
|
|
),
|
|
|
|
),
|
2024-03-28 16:25:49 +01:00
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class BackgroundWaveClipper extends CustomClipper<Path> {
|
|
|
|
@override
|
|
|
|
Path getClip(Size size) {
|
|
|
|
var path = Path();
|
|
|
|
path.lineTo(0.0, size.height);
|
|
|
|
|
|
|
|
var firstCurve = Offset(0, size.height - 20);
|
2024-03-29 16:47:25 +01:00
|
|
|
var lastCurve = Offset(40, size.height - 20);
|
2024-03-28 16:25:49 +01:00
|
|
|
|
|
|
|
path.quadraticBezierTo(
|
2024-03-30 14:07:10 +01:00
|
|
|
firstCurve.dx,
|
|
|
|
firstCurve.dy,
|
|
|
|
lastCurve.dx,
|
|
|
|
lastCurve.dy,
|
2024-03-28 16:25:49 +01:00
|
|
|
);
|
|
|
|
|
|
|
|
firstCurve = Offset(0, size.height - 20);
|
2024-03-29 16:47:25 +01:00
|
|
|
lastCurve = Offset(size.width - 40, size.height - 20);
|
2024-03-28 16:25:49 +01:00
|
|
|
|
|
|
|
path.quadraticBezierTo(
|
2024-03-30 14:07:10 +01:00
|
|
|
firstCurve.dx,
|
|
|
|
firstCurve.dy,
|
|
|
|
lastCurve.dx,
|
|
|
|
lastCurve.dy,
|
2024-03-28 16:25:49 +01:00
|
|
|
);
|
|
|
|
|
|
|
|
firstCurve = Offset(size.width, size.height - 20);
|
|
|
|
lastCurve = Offset(size.width, size.height);
|
|
|
|
|
|
|
|
path.quadraticBezierTo(
|
2024-03-30 14:07:10 +01:00
|
|
|
firstCurve.dx,
|
|
|
|
firstCurve.dy,
|
|
|
|
lastCurve.dx,
|
|
|
|
lastCurve.dy,
|
2024-03-28 16:25:49 +01:00
|
|
|
);
|
|
|
|
|
|
|
|
path.lineTo(size.width, 0.0);
|
|
|
|
path.close();
|
|
|
|
|
|
|
|
return path;
|
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
bool shouldReclip(BackgroundWaveClipper oldClipper) => oldClipper != this;
|
|
|
|
}
|
|
|
|
|
|
|
|
class FSliverAppBar extends SliverPersistentHeaderDelegate {
|
2024-04-04 19:03:41 +02:00
|
|
|
final double preferredHeight;
|
2024-03-28 16:25:49 +01:00
|
|
|
final Widget child;
|
2024-04-04 19:03:41 +02:00
|
|
|
const FSliverAppBar({required this.child, this.preferredHeight = 220});
|
2024-03-28 16:25:49 +01:00
|
|
|
|
|
|
|
@override
|
2024-03-30 14:07:10 +01:00
|
|
|
Widget build(
|
|
|
|
BuildContext context, double shrinkOffset, bool overlapsContent) {
|
|
|
|
var adjustedShrinkOffset =
|
|
|
|
shrinkOffset > minExtent ? minExtent : shrinkOffset;
|
2024-03-28 16:25:49 +01:00
|
|
|
double offset = (minExtent - adjustedShrinkOffset);
|
|
|
|
|
2024-03-29 16:47:25 +01:00
|
|
|
if (offset < 4) {
|
|
|
|
offset = 4;
|
|
|
|
}
|
|
|
|
|
2024-03-28 16:25:49 +01:00
|
|
|
return Stack(
|
|
|
|
children: [
|
2024-04-04 19:03:41 +02:00
|
|
|
// const BackgroundWave(
|
|
|
|
// height: preferredHeight,
|
|
|
|
// ),
|
|
|
|
BlurContainer(
|
|
|
|
height: preferredHeight,
|
2024-03-28 16:25:49 +01:00
|
|
|
),
|
|
|
|
Positioned(
|
2024-03-29 16:47:25 +01:00
|
|
|
top: offset,
|
2024-03-28 16:25:49 +01:00
|
|
|
left: 16,
|
|
|
|
right: 16,
|
2024-03-30 14:07:10 +01:00
|
|
|
child: child,
|
2024-03-28 16:25:49 +01:00
|
|
|
)
|
|
|
|
],
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
2024-04-04 19:03:41 +02:00
|
|
|
double get maxExtent => preferredHeight;
|
2024-03-28 16:25:49 +01:00
|
|
|
|
|
|
|
@override
|
2024-04-04 19:03:41 +02:00
|
|
|
double get minExtent => preferredHeight / 2;
|
2024-03-28 16:25:49 +01:00
|
|
|
|
|
|
|
@override
|
|
|
|
bool shouldRebuild(covariant SliverPersistentHeaderDelegate oldDelegate) =>
|
|
|
|
oldDelegate.maxExtent != maxExtent || oldDelegate.minExtent != minExtent;
|
|
|
|
}
|