import 'package:bbyyy/beans/my_coupon_bean_entity.dart'; import 'package:bbyyy/my_tools/const.dart'; import 'package:bbyyy/my_tools/event_bus.dart'; import 'package:bbyyy/my_tools/my_colors.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; class CouponView { CouponView._internal(); //保存单例 static CouponView _singleton = CouponView._internal(); //工厂构造函数 factory CouponView() => _singleton; ticketItem(MyCouponBeanDataData data) { return StatefulBuilder(builder: (BuildContext context, void Function(void Function()) setState) { return Column( children: [ Container( height: 124, margin: EdgeInsets.only(top: 20), width: double.infinity, child: ClipShadowPath( clipper: TicketClipPath(), shadow: Shadow(blurRadius: 5, color: MyColors.c21333333), child: Scaffold( body: Stack( children: [ Column( children: [ Padding( padding: const EdgeInsets.only( left: 16, top: 9, right: 14), child: Row( children: [ Stack( children: [ Container( child: SvgPicture.asset( 'images/svg/优惠券(1).svg', height: 69, width: 69, ), margin: EdgeInsets.only(right: 12), ), Container( height: 69, width: 69, padding: EdgeInsets.only( bottom: 14, left: 16, ), child: Row( children: [ Container( child: Text( '¥', style: TextStyle( color: Colors.white, fontSize: 12), ), padding: EdgeInsets.only(bottom: 2), ), Text( '${data.amount}', style: TextStyle( color: Colors.white, fontSize: 18), ), ], crossAxisAlignment: CrossAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.start, ), ), ], ), Expanded( child: Column( children: [ Text( couponType(data.type), style: TextStyle( color: MyColors.c333333, fontSize: 14), ), Container( margin: EdgeInsets.only(top: 10), child: Text( '有效期至${data.expireDate}', style: TextStyle( color: MyColors.c999999, fontSize: 10), ), ), ], crossAxisAlignment: CrossAxisAlignment.start, ), ), ], ), ), Padding( padding: EdgeInsets.only(left: 16, right: 15, bottom: 7), child: Row( children: [ Visibility( visible: DateTime.parse(data.expireDate) .subtract(Duration(days: 1)) .isBefore(DateTime.now()) || data.used, child: Container( height: 18, width: 46, decoration: BoxDecoration( border: Border.all( color: data.used ? MyColors.cFF4233 : MyColors.cC6C6C6, width: 0.5), borderRadius: BorderRadius.all( Radius.circular(4), ), ), child: Text( data.used ? '已使用' : '即将到期', style: TextStyle( color: data.used ? MyColors.cFF4233 : MyColors.c999999, fontSize: 9), ), alignment: Alignment.center, ), ), Expanded( child: GestureDetector( onTap: () { data.showDetail = !data.showDetail; EventBus().emit('showCouponIndex'); }, behavior: HitTestBehavior.translucent, child: Container( padding: EdgeInsets.all(1), child: Row( children: [ Text( '使用规则', style: TextStyle( color: MyColors.c999999, fontSize: 11), ), Icon( data.showDetail ? Icons.arrow_drop_up : Icons.arrow_drop_down, color: MyColors.c999999, size: 20, ) ], mainAxisAlignment: MainAxisAlignment.end, ), ), ), ), ], ), ) ], mainAxisAlignment: MainAxisAlignment.spaceBetween, ), Container( child: CustomPaint( painter: DashedPainter(), size: Size(double.infinity, 1), ), margin: EdgeInsets.only( top: 124 / 25 * 18, right: 10, left: 10), ) ], ), ), ), ), AnimatedOpacity( duration: Duration(milliseconds: 200), opacity: data.showDetail ? 1 : 0, child: Visibility( visible: data.showDetail, child: Container( width: double.infinity, height: 114, margin: EdgeInsets.only(top: 4), child: ClipShadowPath( shadow: Shadow(blurRadius: 5, color: MyColors.c21333333), clipper: DescriptionClipPath(), child: Scaffold( body: Column( children: [ Container( margin: EdgeInsets.only(top: 16), child: Text( '使用规则', style: TextStyle( color: MyColors.c999999, fontSize: 12), ), alignment: Alignment.center, width: double.infinity, ), Container( margin: EdgeInsets.symmetric(horizontal: 29), child: Text( couponRule(data.type), style: TextStyle( color: MyColors.c999999, fontSize: 12), ), ), ], crossAxisAlignment: CrossAxisAlignment.start, ), ), ), ), ), ) ], ); }); } } class TicketClipPath extends CustomClipper { @override Path getClip(Size size) { print(size); var path = Path() ..moveTo(0, 4) ..quadraticBezierTo(0, 0, 4, 0) ..lineTo(size.width - 4, 0) ..quadraticBezierTo(size.width, 0, size.width, 4) ..lineTo(size.width, size.height / 25 * 18 - 6) ..quadraticBezierTo(size.width - 6, size.height / 25 * 18 - 6, size.width - 6, size.height / 25 * 18) ..quadraticBezierTo(size.width - 6, size.height / 25 * 18 + 6, size.width, size.height / 25 * 18 + 6) ..lineTo(size.width, size.height - 4) ..quadraticBezierTo(size.width, size.height, size.width - 4, size.height) ..lineTo(4, size.height) ..quadraticBezierTo(0, size.height, 0, size.height - 4) ..lineTo(0, size.height / 25 * 18 + 6) ..quadraticBezierTo( 6, size.height / 25 * 18 + 6, 6, size.height / 25 * 18) ..quadraticBezierTo( 6, size.height / 25 * 18 - 6, 0, size.height / 25 * 18 - 6) ..close(); return path; } @override bool shouldReclip(CustomClipper oldClipper) => false; } class TicketClipPath2 extends CustomClipper { @override Path getClip(Size size) { print(size); var path = Path() ..moveTo(0, 4) ..quadraticBezierTo(0, 0, 4, 0) ..lineTo(size.width - 4, 0) ..quadraticBezierTo(size.width, 0, size.width, 4) ..lineTo(size.width, size.height - 39 - 6) ..quadraticBezierTo(size.width - 6, size.height - 39 - 6, size.width - 6, size.height - 39) ..quadraticBezierTo(size.width - 6, size.height - 39 + 6, size.width, size.height - 39 + 6) ..lineTo(size.width, size.height - 4) ..quadraticBezierTo(size.width, size.height, size.width - 4, size.height) ..lineTo(4, size.height) ..quadraticBezierTo(0, size.height, 0, size.height - 4) ..lineTo(0, size.height - 39 + 6) ..quadraticBezierTo(6, size.height - 39 + 6, 6, size.height - 39) ..quadraticBezierTo(6, size.height - 39 - 6, 0, size.height - 39 - 6) ..close(); return path; } @override bool shouldReclip(CustomClipper oldClipper) => false; } class DescriptionClipPath extends CustomClipper { @override Path getClip(Size size) { double h = size.height; double w = size.width; var path = Path() ..moveTo(0, 10) ..quadraticBezierTo(0, 6, 4, 6) ..lineTo(w - 25, 6) ..lineTo(w - 19, 0) ..lineTo(w - 13, 6) ..lineTo(w - 4, 6) ..quadraticBezierTo(w, 6, w, 10) ..lineTo(w, h - 4) ..quadraticBezierTo(w, h, w - 4, h) ..lineTo(4, h) ..quadraticBezierTo(0, h, 0, h - 4) ..close(); return path; } @override bool shouldReclip(CustomClipper oldClipper) => false; } class ClipShadowPath extends StatelessWidget { final Shadow shadow; final CustomClipper clipper; final Widget child; ClipShadowPath({ @required this.shadow, @required this.clipper, @required this.child, }); @override Widget build(BuildContext context) { return CustomPaint( key: UniqueKey(), painter: _ClipShadowShadowPainter( clipper: this.clipper, shadow: this.shadow, ), child: ClipPath(child: child, clipper: this.clipper), ); } } class _ClipShadowShadowPainter extends CustomPainter { final Shadow shadow; final CustomClipper 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; } } class DashedPainter extends CustomPainter { @override void paint(Canvas canvas, Size size) { var paint = Paint() // 创建一个画笔并配置其属性 ..strokeWidth = 1 // 画笔的宽度 ..isAntiAlias = true // 是否抗锯齿 ..color = Color(0xffdbdbdb); // 画笔颜色 var max = size.width; // size获取到宽度 var dashWidth = 5; var dashSpace = 5; double startX = 0; final space = (dashSpace + dashWidth); while (startX < max) { canvas.drawLine( Offset(startX, 0.0), Offset(startX + dashWidth, 0.0), paint); startX += space; } } @override bool shouldRepaint(CustomPainter oldDelegate) => false; }