import 'dart:isolate'; import 'dart:math'; import 'dart:ui'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:ysairplane/code/YSLogin.dart'; import 'package:flutter_screenutil/screenutil.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'dart:math' as math; class YSDatePicker extends StatefulWidget { final ValueSetter choose; const YSDatePicker({Key key, this.choose}) : super(key: key); @override _YSDatePickerState createState() => _YSDatePickerState(); } class _YSDatePickerState extends State { String birthday = DateTime.now().year.toString()+'-'+DateTime.now().month.toString().padLeft(2,'0')+'-'+DateTime.now().day.toString().padLeft(2,'0')+' '+ DateTime.now().hour.toString().padLeft(2,'0')+':'+DateTime.now().minute.toString().padLeft(2,'0'); @override Widget build(BuildContext context) { return Container( color: Colors.transparent, height: 280, child: Column( crossAxisAlignment: CrossAxisAlignment.end, children: [ Container( height: 40, padding: EdgeInsets.only(left: wsp(40),right: wsp(40)), decoration: BoxDecoration( color: Colors.white, border: Border(bottom: BorderSide(width: 0.5,color: Color(0xFFEEEEEE))) ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ GestureDetector( child: Text('取消',style: TextStyle(fontSize: zsp(30),color: Color(0xFF999999)),), onTap: (){ Navigator.pop(context); }, ), GestureDetector( child: Text('确定',style: TextStyle(fontSize: zsp(30),color: Color(0xFF108DE9)),), onTap: (){ widget.choose(birthday); Navigator.pop(context); }, ) ], ), ), Container( height: 240, padding: EdgeInsets.all(10), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.only(topLeft: Radius.circular(20),topRight: Radius.circular(20)) ), child: CupertinoDatePicker( initialDateTime: DateTime.now(), onDateTimeChanged: (date) { birthday = date.year.toString()+'-'+date.month.toString().padLeft(2,'0')+'-'+date.day.toString().padLeft(2,'0')+' '+date.hour.toString().padLeft(2,'0')+':'+date.minute.toString().padLeft(2,'0'); }, //mode: CupertinoDatePickerMode.date, ), ), ], ), ); } } class BottomInputDialog extends StatefulWidget { final Widget inputView; final double height; final Color color; const BottomInputDialog({Key key, this.inputView,this.height,this.color}) : super(key: key); @override _State createState() => _State(); } class _State extends State with WidgetsBindingObserver{ @override void initState() { WidgetsBinding.instance.addObserver(this); super.initState(); } @override void didChangeMetrics() { WidgetsBinding.instance.addPostFrameCallback((_) { if(MediaQuery.of(context).viewInsets.bottom <= 0){ Navigator.pop(context); if (!mounted) { return; } WidgetsBinding.instance.removeObserver(this); } }); super.didChangeMetrics(); } @override void dispose() { super.dispose(); if (!mounted) { return; } WidgetsBinding.instance.removeObserver(this); } @override Widget build(BuildContext context) { return CupertinoPageScaffold( backgroundColor: Colors.transparent, child: Stack( children: [ GestureDetector( child: BackdropFilter( filter: ImageFilter.blur(sigmaX: 3, sigmaY: 3), child: Container( height: MediaQuery.of(context).size.height, color: widget.color!=null?widget.color:Colors.black12.withOpacity(0.8), ), ), onTap: () { Navigator.pop(context); if (!mounted) { return; } WidgetsBinding.instance.removeObserver(this); }, ), Container( margin: EdgeInsets.only(top: MediaQuery.of(context).size.height-widget.height-MediaQuery.of(context).viewInsets.bottom), height: widget.height, decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.only(topLeft: Radius.circular(10),topRight: Radius.circular(10)), boxShadow: [ BoxShadow( color: Colors.black12, offset: Offset(-1, -3), blurRadius: 5 ) ] ), padding: EdgeInsets.all(10), child: widget.inputView, ) ], ), ); } } class PopRoute extends PopupRoute{ final Duration _duration = Duration(milliseconds: 300); Widget child; PopRoute({@required this.child}); @override Color get barrierColor => null; @override bool get barrierDismissible => true; @override String get barrierLabel => null; @override Widget buildPage(BuildContext context, Animation animation, Animation secondaryAnimation) { return child; } @override Duration get transitionDuration => _duration; } wsp(int number){ // return ScreenUtil().setWidth(number); return number*0.5; } hsp(int number){ return number*0.5; //return ScreenUtil().setHeight(number); } zsp(int number){ return number*0.5; //return ScreenUtil().setSp(number,allowFontScalingSelf: false); } isLogin(BuildContext context,{VoidCallback login}) async{ SharedPreferences prefs = await SharedPreferences.getInstance(); String token = prefs.getString('token'); if(token==null){ Navigator.of(context,rootNavigator: true).push( CupertinoPageRoute( builder: (context){ return YSLogin(); } ) ).then((value){ if(value!=null){ login(); } }); }else{ login(); } } ///手机号验证 bool isChinaPhoneLegal(String str) { return RegExp(r"^1([38][0-9]|4[579]|5[0-3,5-9]|6[6]|7[0135678]|9[89])\d{8}$").hasMatch(str); } ///邮箱验证 bool isEmail(String str) { return RegExp(r"^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$").hasMatch(str); } ///验证URL bool isUrl(String value) { return RegExp(r"^((https|http|ftp|rtsp|mms)?:\/\/)[^\s]+").hasMatch(value); } ///验证身份证 bool isIdCard(String value) { return RegExp(r"\d{17}[\d|x]|\d{15}").hasMatch(value); } ///验证中文 bool isChinese(String value) { return RegExp(r"[\u4e00-\u9fa5]").hasMatch(value); } class LogUtil { static var _separator = "="; static var _split = "$_separator$_separator$_separator$_separator$_separator$_separator$_separator$_separator$_separator"; static var _title = "Yl-Log"; static var _isDebug = true; static int _limitLength = 800; static String _startLine = "$_split$_title$_split"; static String _endLine = "$_split$_separator$_separator$_separator$_split"; static void init({String title, @required bool isDebug,int limitLength}) { _title = title; _isDebug = isDebug; _limitLength = limitLength??=_limitLength; _startLine = "$_split$_title$_split"; var endLineStr = StringBuffer(); var cnCharReg = RegExp("[\u4e00-\u9fa5]"); for (int i = 0; i < _startLine.length; i++) { if (cnCharReg.stringMatch(_startLine[i]) != null) { endLineStr.write(_separator); } endLineStr.write(_separator); } _endLine = endLineStr.toString(); } //仅Debug模式可见 static void d(dynamic obj) { if (_isDebug) { _log(obj.toString()); } } static void v(dynamic obj) { _log(obj.toString()); } static void _log(String msg) { print("$_startLine"); _logEmpyLine(); if(msg.length<_limitLength){ print(msg); }else{ segmentationLog(msg); } _logEmpyLine(); print("$_endLine"); } static void segmentationLog(String msg) { var outStr = StringBuffer(); for (var index = 0; index < msg.length; index++) { outStr.write(msg[index]); if (index % _limitLength == 0 && index!=0) { print(outStr); outStr.clear(); var lastIndex = index+1; if(msg.length-lastIndex<_limitLength){ var remainderStr = msg.substring(lastIndex,msg.length); print(remainderStr); break; } } } } static void _logEmpyLine(){ print(""); } } //indicate Widget indicateString(String longStr,String str,String otherStr){ List strings = longStr.split(str); print(strings); return Container( child: RichText( text: longStr!=str?TextSpan( children: [ for(int i = 0;i createState() { return _ExpandableTextState(text, maxLines, style, expand); } } class _ExpandableTextState extends State { final String text; final int maxLines; final TextStyle style; bool expand; _ExpandableTextState(this.text, this.maxLines, this.style, this.expand) { if (expand == null) { expand = false; } } @override Widget build(BuildContext context) { return LayoutBuilder(builder: (context, size) { final span = TextSpan(text: text ?? '', style: style); final tp = TextPainter( text: span, maxLines: maxLines, textDirection: TextDirection.ltr); tp.layout(maxWidth: size.maxWidth); if (tp.didExceedMaxLines) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ expand ? Text(text ?? '', style: style) : Text(text ?? '', maxLines: maxLines, overflow: TextOverflow.ellipsis, style: style), GestureDetector( behavior: HitTestBehavior.translucent, onTap: () { setState(() { expand = !expand; }); }, child: Container( padding: EdgeInsets.only(top: 2), child: Text(expand ? '收起' : '全文', style: TextStyle( fontSize: style != null ? style.fontSize : null, color: Colors.blue)), ), ), ], ); } else { return Text(text ?? '', style: style); } }); } } Widget ysTextExpend({String text,int maxLines,TextStyle style,bool expand = false}) { return StatefulBuilder( builder: (context,ysState){ return LayoutBuilder(builder: (context, size) { final span = TextSpan(text: text ?? '', style: style); final tp = TextPainter( text: span, maxLines: maxLines, textDirection: TextDirection.ltr); tp.layout(maxWidth: size.maxWidth); if (tp.didExceedMaxLines) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ expand ? Text(text ?? '', style: style) : Text(text ?? '', maxLines: maxLines, overflow: TextOverflow.ellipsis, style: style), GestureDetector( behavior: HitTestBehavior.translucent, onTap: () { ysState(() { expand = !expand; }); }, child: Container( padding: EdgeInsets.only(top: 2), child: Text(expand ? '收起' : '全文', style: TextStyle( fontSize: style != null ? style.fontSize : null, color: Colors.blue)), ), ), ], ); } else { return Text(text ?? '', style: style); } }); }, ); } class YSPicker extends StatefulWidget { final ValueSetter choose; final List dataArray; final String title; const YSPicker({Key key, this.choose, this.dataArray, this.title}) : super(key: key); @override _YSPickerState createState() => _YSPickerState(); } class _YSPickerState extends State { var _value; @override Widget build(BuildContext context) { _value = widget.dataArray[0]; return Container( color: Colors.transparent, height: hsp(600), child: Column( crossAxisAlignment: CrossAxisAlignment.end, children: [ Container( height: hsp(100), padding: EdgeInsets.only(left: wsp(40),right: wsp(40)), decoration: BoxDecoration( color: Colors.white, border: Border(bottom: BorderSide(width: 0.5,color: Color(0xFFEEEEEE))) ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ GestureDetector( child: Text('取消',style: TextStyle(fontSize: zsp(30),color: Color(0xFF999999)),), onTap: (){ Navigator.pop(context); }, ), GestureDetector( child: Text('确定',style: TextStyle(fontSize: zsp(30),color: Color(0xFF108DE9)),), onTap: (){ widget.choose(_value); Navigator.pop(context); }, ) ], ), ), Container( height: hsp(500), padding: EdgeInsets.all(10), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.only(topLeft: Radius.circular(20),topRight: Radius.circular(20)) ), child: CupertinoPicker( children: [ for(int i=0;i=0&&date.difference(date).inHours<24){ tagStr = '今天'; }else if(date.difference(date).inHours>=24&&date.difference(date).inHours<48){ tagStr = '明天'; }else if(date.difference(date).inHours>=48&&date.difference(date).inHours<72){ tagStr = '后天'; }else{ switch(date.weekday){ case 1: tagStr = '周一';break; case 2: tagStr = '周二';break; case 3: tagStr = '周三';break; case 4: tagStr = '周四';break; case 5: tagStr = '周五';break; case 6: tagStr = '周六';break; case 7: tagStr = '周日';break; } } return tagStr; } class DashedRect extends StatelessWidget { final Color color; final double strokeWidth; final double gap; DashedRect( {this.color = Colors.black, this.strokeWidth = 1.0, this.gap = 5.0}); @override Widget build(BuildContext context) { return Container( child: Padding( padding: EdgeInsets.all(strokeWidth / 2), child: CustomPaint( painter: DashRectPainter(color: color, strokeWidth: strokeWidth, gap: gap), ), ), ); } } class DashRectPainter extends CustomPainter { double strokeWidth; Color color; double gap; DashRectPainter( {this.strokeWidth = 5.0, this.color = Colors.red, this.gap = 5.0}); @override void paint(Canvas canvas, Size size) { Paint dashedPaint = Paint() ..color = color ..strokeWidth = strokeWidth ..style = PaintingStyle.stroke; double x = size.width; double y = size.height; Path _topPath = getDashedPath( a: math.Point(0, 0), b: math.Point(x, 0), gap: gap, ); Path _rightPath = getDashedPath( a: math.Point(x, 0), b: math.Point(x, y), gap: gap, ); Path _bottomPath = getDashedPath( a: math.Point(0, y), b: math.Point(x, y), gap: gap, ); Path _leftPath = getDashedPath( a: math.Point(0, 0), b: math.Point(0.001, y), gap: gap, ); canvas.drawPath(_topPath, dashedPaint); canvas.drawPath(_rightPath, dashedPaint); canvas.drawPath(_bottomPath, dashedPaint); canvas.drawPath(_leftPath, dashedPaint); } Path getDashedPath({ @required math.Point a, @required math.Point b, @required gap, }) { Size size = Size(b.x - a.x, b.y - a.y); Path path = Path(); path.moveTo(a.x, a.y); bool shouldDraw = true; math.Point currentPoint = math.Point(a.x, a.y); num radians = math.atan(size.height / size.width); num dx = math.cos(radians) * gap < 0 ? math.cos(radians) * gap * -1 : math.cos(radians) * gap; num dy = math.sin(radians) * gap < 0 ? math.sin(radians) * gap * -1 : math.sin(radians) * gap; while (currentPoint.x <= b.x && currentPoint.y <= b.y) { shouldDraw ? path.lineTo(currentPoint.x, currentPoint.y) : path.moveTo(currentPoint.x, currentPoint.y); shouldDraw = !shouldDraw; currentPoint = math.Point( currentPoint.x + dx, currentPoint.y + dy, ); } return path; } @override bool shouldRepaint(CustomPainter oldDelegate) { return true; } } getSecretStr(String str) { String secret = str.length==11?'****':'***********'; return str.substring(0,3)+secret+str.substring(str.length-4,str.length); } isolateCountEven(var model) async { final response = ReceivePort(); await Isolate.spawn(countEvent2, response.sendPort); final sendPort = await response.first; final answer = ReceivePort(); sendPort.send([answer.sendPort, model]); return answer.first; } countEvent2(SendPort port) { final rPort = ReceivePort(); port.send(rPort.sendPort); rPort.listen((message) { final send = message[0] as SendPort; final model = message[1]; send.send(countEven(model)); }); } countEven(var model){ } class CirclePageRoute extends PageRoute { CirclePageRoute({ @required this.builder, this.transitionDuration = const Duration(milliseconds: 500), this.opaque = true, this.barrierDismissible = false, this.barrierColor, this.barrierLabel, this.maintainState = true, }); final WidgetBuilder builder; @override final Duration transitionDuration; @override final bool opaque; @override final bool barrierDismissible; @override final Color barrierColor; @override final String barrierLabel; @override final bool maintainState; @override Widget buildPage(BuildContext context, Animation animation, Animation secondaryAnimation) { return AnimatedBuilder( animation: animation, builder: (context, child) { return ClipPath( clipper: CirclePath(animation.value), child: child, ); }, child: builder(context), ); } } class CirclePath extends CustomClipper { CirclePath(this.value); final double value; @override Path getClip(Size size) { var path = Path(); double radius = value * sqrt(size.height * size.height + size.width * size.width); path.addOval(Rect.fromLTRB( size.width - radius, -radius, size.width + radius, radius)); return path; } @override bool shouldReclip(CustomClipper oldClipper) { return true; } }