import 'package:flutter/material.dart'; const double _width = 170; const double _height = 38; class TitleClipRect extends StatelessWidget { const TitleClipRect({ super.key, this.color = Colors.grey, required this.title, required this.arrowHeight, required this.clickTitle, }); final Color? color; final String title; final double arrowHeight; final Function clickTitle; @override Widget build(BuildContext context) { return InkWell( onTap: () { clickTitle.call(); }, customBorder: HoleShapeBorder(arrowHeight), child: Card( margin: const EdgeInsets.all(0), shape: HoleShapeBorder(arrowHeight), color: color, elevation: color == null ? 5 : 0, shadowColor: Theme.of(context).primaryColor.withOpacity(0.8), child: ClipPath( clipper: TitleClipPath(arrowHeight), child: Container( width: _width, height: _height, padding: const EdgeInsets.symmetric( horizontal: 15, ), decoration: BoxDecoration( boxShadow: [ BoxShadow( color: Theme.of(context).primaryColor.withOpacity(1), ), ], color: color, ), alignment: Alignment.center, child: FittedBox( child: Text( title, style: const TextStyle(color: Colors.white, fontSize: 20), ), ), ), ), ), ); } } class TitleClipPath extends CustomClipper { final double arrowHeight; TitleClipPath(this.arrowHeight); @override Path getClip(Size size) { final height = size.height; final arrowBase = height / 2; // final arrowPLine = math.tan(120 / 180) * arrowBase; final path = Path(); path.moveTo(0, 0); // 左上角 path.lineTo(size.width - arrowHeight, 0); // 右上角 path.lineTo(size.width, arrowBase); // 右端点 path.lineTo(size.width - arrowHeight, height); // 右下角 path.lineTo(0, height); // 左下角 path.lineTo(arrowHeight, arrowBase); // 左端点 path.lineTo(0, 0); // 左上角 return path; } @override bool shouldReclip(covariant CustomClipper oldClipper) { return false; } } class HoleShapeBorder extends ShapeBorder { final Offset offset; final double size; final double arrowHeight; const HoleShapeBorder(this.arrowHeight, {this.offset = const Offset(0, 0), this.size = 0}); @override EdgeInsetsGeometry get dimensions => throw UnimplementedError(); @override void paint(Canvas canvas, Rect rect, {TextDirection? textDirection}) {} @override Path getOuterPath(Rect rect, {TextDirection? textDirection}) { var path = Path(); final height = rect.size.height; final arrowBase = height / 2; path.moveTo(0, 0); // 左上角 path.lineTo(rect.size.width - arrowHeight, 0); // 右上角 path.lineTo(rect.size.width, arrowBase); // 右端点 path.lineTo(rect.size.width - arrowHeight, height); // 右下角 path.lineTo(0, height); // 左下角 path.lineTo(arrowHeight, arrowBase); // 左端点 path.lineTo(0, 0); // 左上角 return path; } @override ShapeBorder scale(double t) { // TODO: implement scale throw UnimplementedError(); } @override Path getInnerPath(Rect rect, {TextDirection? textDirection}) { // TODO: implement getInnerPath throw UnimplementedError(); } }