novyronst/lib/pages/widgets/cut_corner_clipper.dart

101 lines
2.3 KiB
Dart

import 'package:flutter/material.dart';
class CutCornerClipper extends StatelessWidget {
const CutCornerClipper({super.key,
this.width,
this.height,
this.cutCorner = CutCorner.topRight,
this.cutSize,
this.child,
});
final double? width;
final double? height;
final CutCorner cutCorner;
final double? cutSize;
final Widget? child;
@override
Widget build(BuildContext context) {
return ClipPath(
clipper: EqualCutCornerClipper(
cutSize: cutSize ?? 35,
corner: cutCorner,
),
child: Container(
width: width,
height: height,
decoration: BoxDecoration(
color: Colors.white,
),
child: child,
),
);
}
}
/// 长方形缺一个角(等边缺角)
class EqualCutCornerClipper extends CustomClipper<Path> {
final double cutSize; // 缺角两条直角边的长度(相等)
final CutCorner corner;
const EqualCutCornerClipper({
this.cutSize = 20,
this.corner = CutCorner.topRight,
});
@override
Path getClip(Size size) {
final path = Path();
final w = size.width;
final h = size.height;
final c = cutSize;
switch (corner) {
case CutCorner.topRight:
path.moveTo(0, 0);
path.lineTo(w - c, 0); // 上边到缺角起点
path.lineTo(w, c); // 🔥 45° 斜线(两条边相等)
path.lineTo(w, h);
path.lineTo(0, h);
break;
case CutCorner.topLeft:
path.moveTo(c, 0);
path.lineTo(w, 0);
path.lineTo(w, h);
path.lineTo(0, h);
path.lineTo(0, c);
break;
case CutCorner.bottomRight:
path.moveTo(0, 0);
path.lineTo(w, 0);
path.lineTo(w, h - c);
path.lineTo(w - c, h);
path.lineTo(0, h);
break;
case CutCorner.bottomLeft:
path.moveTo(0, 0);
path.lineTo(w, 0);
path.lineTo(w, h);
path.lineTo(c, h);
path.lineTo(0, h - c);
break;
}
path.close();
return path;
}
@override
bool shouldReclip(covariant CustomClipper<Path> oldClipper) {
if (oldClipper is EqualCutCornerClipper) {
return oldClipper.cutSize != cutSize || oldClipper.corner != corner;
}
return true;
}
}
enum CutCorner { topLeft, topRight, bottomLeft, bottomRight }