使用 Material 的 ShowDialog 组件自定义弹窗
void showComfirm(BuildContext context, String msg,
{Function comfirm,
Function cancel,
String comfirmTitle = '确认',
String cancelTitle = '取消'}) {
showDialog(
context: context,
builder: (BuildContext context) {
return CustomDialog(
backgroundColor: Color(0xffffffff),
shape: RoundedRectangleBorder(
borderRadius:
BorderRadius.circular(ScreenUtil.getInstance().setSize(16))),
minWidth: ScreenUtil.getInstance().setSize(480),
maxWidth: ScreenUtil.getInstance().setSize(480),
minHeight: ScreenUtil.getInstance().setSize(240),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Container(
constraints: BoxConstraints(
minHeight: ScreenUtil.getInstance().setSize(150),
),
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(
color: kLingyiGray,
width: ScreenUtil.getInstance().setSize(1),
))),
width: ScreenUtil.getInstance().setSize(480),
padding: EdgeInsets.fromLTRB(
ScreenUtil.getInstance().setSize(34),
ScreenUtil.getInstance().setSize(34),
ScreenUtil.getInstance().setSize(34),
ScreenUtil.getInstance().setSize(34)),
child: Text(
msg,
style: TextStyle(
fontSize: ScreenUtil.getInstance().setSp(32),
color: kLingyiText500),
),
),
Container(
height: ScreenUtil.getInstance().setSize(88),
child: Flex(
direction: Axis.horizontal,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Expanded(
flex: 1,
child: GestureDetector(
onTap: () {
Navigator.of(context).pop();
if (cancel != null) cancel();
},
child: Text(
cancelTitle,
style: TextStyle(
fontSize: ScreenUtil.getInstance().setSp(28),
color: Color(0xff999999)),
textAlign: TextAlign.center,
),
)),
Container(
width: ScreenUtil.getInstance().setSize(1),
height: ScreenUtil.getInstance().setSize(88),
color: kLingyiGray,
),
Expanded(
flex: 1,
child: GestureDetector(
onTap: () {
Navigator.of(context).pop();
if (comfirm != null) comfirm();
},
child: Text(
comfirmTitle,
style: TextStyle(
fontSize: ScreenUtil.getInstance().setSp(28),
color: Color(0xff4499ff)),
textAlign: TextAlign.center,
),
))
],
),
),
],
),
);
});
}
void showAlert(BuildContext context, String msg,
{Function callback, String comfirmTitle = '确认'}) {
showDialog(
context: context,
builder: (BuildContext context) {
return CustomDialog(
backgroundColor: Color(0xffffffff),
shape: RoundedRectangleBorder(
borderRadius:
BorderRadius.circular(ScreenUtil.getInstance().setSize(16))),
minWidth: ScreenUtil.getInstance().setSize(480),
maxWidth: ScreenUtil.getInstance().setSize(480),
minHeight: ScreenUtil.getInstance().setSize(240),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Container(
constraints: BoxConstraints(
minHeight: ScreenUtil.getInstance().setSize(150),
),
width: ScreenUtil.getInstance().setSize(480),
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(
color: kLingyiGray,
width: ScreenUtil.getInstance().setSize(1),
))),
padding: EdgeInsets.fromLTRB(
ScreenUtil.getInstance().setSize(34),
ScreenUtil.getInstance().setSize(34),
ScreenUtil.getInstance().setSize(34),
ScreenUtil.getInstance().setSize(34)),
child: Text(
msg,
style: TextStyle(
fontSize: ScreenUtil.getInstance().setSp(32),
color: kLingyiText500),
textAlign: TextAlign.center,
),
),
GestureDetector(
onTap: () {
Navigator.of(context).pop();
if (callback != null) callback();
},
child: Container(
height: ScreenUtil.getInstance().setSize(88),
alignment: Alignment.center,
child: Text(
comfirmTitle,
style: TextStyle(
fontSize: ScreenUtil.getInstance().setSp(28),
color: Color(0xff4499ff)),
),
),
)
],
),
);
});
}
void showToast(BuildContext context, String msg,
{Function callback, int duration = 1500, bool isSuccess = true}) {
Timer(Duration(milliseconds: duration), () {
Navigator.pop(context);
if (callback != null) callback();
});
customShowDialog(
context: context,
barrierDismissible: false,
barrierColor: Color(0x00ffffff),
builder: (BuildContext context) {
return CustomDialog(
backgroundColor: Color(0x88000000),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(
ScreenUtil.getInstance().setSize(12))),
elevation: 0,
child: Padding(
padding: EdgeInsets.fromLTRB(20, 15, 20, 15),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Icon(
isSuccess ? Icons.done : Icons.error,
size: ScreenUtil.getInstance().setSize(80),
color: kLingyiWhite,
),
SizedBox(
height: ScreenUtil.getInstance().setSize(20),
),
Text(
msg,
style: TextStyle(
color: kLingyiWhite,
fontSize: ScreenUtil.getInstance().setSp(28)),
textAlign: TextAlign.center,
maxLines: 3,
overflow: TextOverflow.ellipsis,
)
],
),
));
});
}
void showMsg(BuildContext context, String msg,
{int duration = 1500, Function callback}) {
Timer(Duration(milliseconds: duration), () {
Navigator.of(context).pop();
if (callback != null) callback();
});
customShowDialog(
context: context,
barrierDismissible: false,
barrierColor: Color(0x00ffffff),
builder: (BuildContext context) {
return CustomDialog(
backgroundColor: Color(0x88000000),
shape: RoundedRectangleBorder(
borderRadius:
BorderRadius.circular(ScreenUtil.getInstance().setSize(8))),
elevation: 0,
minWidth: ScreenUtil.getInstance().setSize(300),
maxWidth: ScreenUtil.getInstance().setSize(650),
minHeight: ScreenUtil.getInstance().setSize(64),
child: Stack(
alignment: Alignment.center,
children: <Widget>[
Padding(
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
child: Text(
msg,
style: TextStyle(
color: kLingyiWhite,
fontSize: ScreenUtil.getInstance().setSp(28)),
textAlign: TextAlign.center,
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
)
],
));
});
}
class CustomDialog extends StatelessWidget {
const CustomDialog({
Key key,
this.backgroundColor,
this.elevation,
this.insetAnimationDuration = const Duration(milliseconds: 100),
this.insetAnimationCurve = Curves.decelerate,
this.shape,
this.child,
this.minWidth,
this.maxWidth,
this.minHeight,
this.maxHeight,
}) : super(key: key);
final Color backgroundColor;
final double elevation;
final Duration insetAnimationDuration;
final Curve insetAnimationCurve;
final ShapeBorder shape;
final Widget child;
final double minWidth;
final double maxWidth;
final double minHeight;
final double maxHeight;
static const RoundedRectangleBorder _defaultDialogShape =
RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(2.0)));
static const double _defaultElevation = 24.0;
@override
Widget build(BuildContext context) {
final DialogTheme dialogTheme = DialogTheme.of(context);
return AnimatedPadding(
padding: MediaQuery.of(context).viewInsets +
const EdgeInsets.symmetric(horizontal: 0, vertical: 0),
duration: insetAnimationDuration,
curve: insetAnimationCurve,
child: MediaQuery.removeViewInsets(
removeLeft: true,
removeTop: true,
removeRight: true,
removeBottom: true,
context: context,
child: Center(
child: ConstrainedBox(
constraints: BoxConstraints(
minWidth: minWidth ?? ScreenUtil.getInstance().setSize(200),
minHeight: minHeight ?? ScreenUtil.getInstance().setSize(200),
maxWidth: maxWidth ?? ScreenUtil.getInstance().setSize(600),
maxHeight: maxWidth ?? ScreenUtil.getInstance().setSize(600),
),
child: Material(
color: backgroundColor ??
dialogTheme.backgroundColor ??
Theme.of(context).dialogBackgroundColor,
elevation:
elevation ?? dialogTheme.elevation ?? _defaultElevation,
shape: shape ?? dialogTheme.shape ?? _defaultDialogShape,
type: MaterialType.card,
child: child,
),
),
),
),
);
}
}
Future<T> customShowDialog<T>({
@required
BuildContext context,
bool barrierDismissible = true,
Color barrierColor = Colors.black54,
@Deprecated(
'Instead of using the "child" argument, return the child from a closure '
'provided to the "builder" argument. This will ensure that the BuildContext '
'is appropriate for widgets built in the dialog.')
Widget child,
WidgetBuilder builder,
}) {
assert(child == null || builder == null);
assert(debugCheckHasMaterialLocalizations(context));
final ThemeData theme = Theme.of(context, shadowThemeOnly: true);
return showGeneralDialog(
context: context,
pageBuilder: (BuildContext buildContext, Animation<double> animation,
Animation<double> secondaryAnimation) {
final Widget pageChild = child ?? Builder(builder: builder);
return SafeArea(
child: Builder(builder: (BuildContext context) {
return theme != null
? Theme(data: theme, child: pageChild)
: pageChild;
}),
);
},
barrierDismissible: barrierDismissible,
barrierLabel: MaterialLocalizations.of(context).modalBarrierDismissLabel,
barrierColor: barrierColor,
transitionDuration: const Duration(milliseconds: 150),
transitionBuilder: _buildMaterialDialogTransitions,
);
}
Widget _buildMaterialDialogTransitions(
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child) {
return FadeTransition(
opacity: CurvedAnimation(
parent: animation,
curve: Curves.easeOut,
),
child: child,
);
}
使用 Material 的 OverlayEntry组件自定义弹窗
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:lingyi/config/color.dart';
class ShowMsg {
static void show(BuildContext context, String msg ,{
int duration = 1500,
int gravity = 1,
Color backgroundColor = const Color(0x88000000),
Color textColor = Colors.white,
double backgroundRadius,
Border border,
Function callback
}) {
MsgView.dismiss();
ToastView.dismiss();
MsgView.createView(
msg, context, duration, gravity, backgroundColor, textColor, backgroundRadius, border, callback);
}
}
class MsgView {
static final MsgView _singleton = new MsgView._internal();
factory MsgView() {
return _singleton;
}
MsgView._internal();
static OverlayState overlayState;
static OverlayEntry _overlayEntry;
static bool _isVisible = false;
static void createView(String msg, BuildContext context, int duration, int gravity,
Color background, Color textColor, double backgroundRadius, Border border, Function callback) async {
overlayState = Overlay.of(context);
_overlayEntry = new OverlayEntry(
builder: (BuildContext context) => PositionWidget(
widget: Container(
width: MediaQuery.of(context).size.width,
child: Container(
alignment: Alignment.center,
width: MediaQuery.of(context).size.width,
child: Container(
decoration: BoxDecoration(
color: background,
borderRadius: BorderRadius.circular(backgroundRadius ?? ScreenUtil.getInstance().setSize(8)),
border: border,
),
constraints: BoxConstraints(
minWidth: ScreenUtil.getInstance().setSize(300),
maxWidth: ScreenUtil.getInstance().setSize(650),
minHeight: ScreenUtil.getInstance().setSize(64),
),
margin: EdgeInsets.symmetric(horizontal: 20),
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
child: Stack(
alignment: Alignment.center,
children: <Widget>[
Text(msg, softWrap: true, style: TextStyle(fontSize: ScreenUtil.getInstance().setSize(28), color: textColor)),
]
)
)),
),
gravity: gravity),
);
_isVisible = true;
overlayState.insert(_overlayEntry);
await new Future.delayed(Duration(milliseconds: duration ?? 2000));
if(callback != null) callback();
dismiss();
}
static dismiss() async {
if (!_isVisible) {
return;
}
_isVisible = false;
_overlayEntry?.remove();
}
}
class PositionWidget extends StatelessWidget {
PositionWidget({
Key key,
@required this.widget,
@required this.gravity,
}) : super(key: key);
final Widget widget;
final int gravity;
@override
Widget build(BuildContext context) {
return new Positioned(
top: gravity == 2 ? 50 : null,
bottom: gravity == 0 ? 50 : null,
child: Material(
color: Colors.transparent,
child: widget,
));
}
}
// show Tost----------------------------------------------
class ShowToast {
static void show(BuildContext context, String msg ,{
bool isSuccess = true,
int duration = 1500,
Color backgroundColor,
Color textColor = Colors.white,
double backgroundRadius,
Function callback
}) {
MsgView.dismiss();
ToastView.dismiss();
ToastView.createView(
msg, context, isSuccess, duration, backgroundColor, textColor, backgroundRadius, callback);
}
}
class ToastView {
static final ToastView _singleton = new ToastView._internal();
factory ToastView() {
return _singleton;
}
ToastView._internal();
static OverlayState overlayState;
static OverlayEntry _overlayEntry;
static bool _isVisible = false;
static void createView(String msg, BuildContext context, bool isSuccess, int duration, Color background, Color textColor, double backgroundRadius, Function callback) async {
overlayState = Overlay.of(context);
_overlayEntry = new OverlayEntry(
builder: (BuildContext context) => PositionWidget(
widget: Stack(
alignment: Alignment.center,
children: <Widget>[
Container(
decoration: BoxDecoration(
color: background ?? Color(0x88000000),
borderRadius: BorderRadius.circular(backgroundRadius ?? ScreenUtil.getInstance().setSize(12))
),
padding: EdgeInsets.fromLTRB(20, 10, 20, 10),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Icon(
isSuccess ? Icons.done : Icons.error,
size: ScreenUtil.getInstance().setSize(80),
color: textColor,
),
SizedBox(
height: ScreenUtil.getInstance().setSize(10),
),
Text(
msg,
style: TextStyle(
color: textColor,
fontSize: ScreenUtil.getInstance().setSp(28)),
textAlign: TextAlign.center,
maxLines: 3,
overflow: TextOverflow.ellipsis,
)
],
),
)
],
),
gravity: 1),
);
_isVisible = true;
overlayState.insert(_overlayEntry);
await new Future.delayed(Duration(milliseconds: duration ?? 2000));
if(callback != null) callback();
dismiss();
}
static dismiss() async {
if (!_isVisible) {
return;
}
_isVisible = false;
_overlayEntry?.remove();
}
}
// show Alert---------------------------------------------
class ShowAlert {
static void show(BuildContext context, String msg ,{
Color backgroundColor,
double backgroundRadius,
bool showCancel: true,
String comfirmTitle: '确认',
String cancelTitle: '取消',
Function onConfirm,
Function onCancel
}) {
MsgView.dismiss();
ToastView.dismiss();
AlertView.dismiss();
AlertView.createView(msg, context, backgroundColor, backgroundRadius, showCancel, comfirmTitle, cancelTitle, onConfirm, onCancel);
}
}
class AlertView {
static final AlertView _singleton = new AlertView._internal();
factory AlertView() {
return _singleton;
}
AlertView._internal();
static OverlayState overlayState;
static OverlayEntry _overlayEntry;
static bool _isVisible = false;
static void createView(String msg, BuildContext context, Color backgroundColor, double backgroundRadius, bool showCancel, String comfirmTitle, String cancelTitle, Function onConfirm, Function onCancel) async {
overlayState = Overlay.of(context);
_overlayEntry = new OverlayEntry(
builder: (BuildContext context) => PositionWidget(
widget: Container(
color: Color(0x66000000),
child: Stack(
alignment: Alignment.center,
children: <Widget>[
Container(
decoration: BoxDecoration(
color: backgroundColor ?? Colors.white,
borderRadius: BorderRadius.circular(backgroundRadius ?? ScreenUtil.getInstance().setSize(16))
),
constraints: BoxConstraints(
minWidth: ScreenUtil.getInstance().setSize(480),
maxWidth: ScreenUtil.getInstance().setSize(480),
minHeight: ScreenUtil.getInstance().setSize(240),
),
padding: EdgeInsets.fromLTRB(0, 10, 0, 10),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Container(
constraints: BoxConstraints(
minHeight: ScreenUtil.getInstance().setSize(150),
),
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(
color: kLingyiGray,
width: ScreenUtil.getInstance().setSize(1),
))),
width: ScreenUtil.getInstance().setSize(480),
padding: EdgeInsets.fromLTRB(
ScreenUtil.getInstance().setSize(34),
ScreenUtil.getInstance().setSize(34),
ScreenUtil.getInstance().setSize(34),
ScreenUtil.getInstance().setSize(34)),
child: Text(
msg,
style: TextStyle(
fontSize: ScreenUtil.getInstance().setSp(32),
color: kLingyiText500),
),
),
Container(
height: ScreenUtil.getInstance().setSize(88),
child: !showCancel ?
GestureDetector(
onTap: () {
dismiss();
if (onConfirm != null) onConfirm();
},
child: Center(
child: Text(
comfirmTitle,
style: TextStyle(
fontSize: ScreenUtil.getInstance().setSp(28),
color: Color(0xff4499ff)),
textAlign: TextAlign.center,
)
),
) : Flex(
direction: Axis.horizontal,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Expanded(
flex: 1,
child: GestureDetector(
onTap: () {
dismiss();
if (onCancel != null) onCancel();
},
child: Text(
cancelTitle,
style: TextStyle(
fontSize: ScreenUtil.getInstance().setSp(28),
color: Color(0xff999999)),
textAlign: TextAlign.center,
),
)
),
Container(
width: ScreenUtil.getInstance().setSize(1),
height: ScreenUtil.getInstance().setSize(88),
color: kLingyiGray,
),
Expanded(
flex: 1,
child: GestureDetector(
onTap: () {
dismiss();
if (onConfirm != null) onConfirm();
},
child: Text(
comfirmTitle,
style: TextStyle(
fontSize: ScreenUtil.getInstance().setSp(28),
color: Color(0xff4499ff)),
textAlign: TextAlign.center,
),
)
)
],
),
),
],
),
)
],
),
),
gravity: 1),
);
_isVisible = true;
overlayState.insert(_overlayEntry);
}
static dismiss() async {
if (!_isVisible) {
return;
}
_isVisible = false;
_overlayEntry?.remove();
}
}
使用 Material 的 showModalBottomSheet 和 Cupertino 的 CupertinoPicker 制作底部抽屉选择器
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:annotation_route/route.dart';
import 'package:lingyi/config/color.dart';
import 'package:lingyi/route/route.dart';
import 'package:lingyi/util/common.dart';
@ARoute(url: 'page://health/medicine')
class Medicine extends StatefulWidget {
final dynamic option;
Medicine(this.option);
@override
MedicineState createState() => MedicineState();
}
class MedicineState extends State<Medicine> {
bool isWork = true; // 是否提醒
List<Map> startList = [];
List<Map> endList = [];
List<Map> weekList = [{'isPick': false, 'showValue': '周一'},{'isPick': false, 'showValue': '周二'},{'isPick': false, 'showValue': '周三'},{'isPick': false, 'showValue': '周四'},{'isPick': false, 'showValue': '周五'},{'isPick': false, 'showValue': '周六'},{'isPick': false, 'showValue': '周日'},{'isPick': false, 'showValue': '每天'}];
List<String> durationList = ['7天','30天','90天','180天','365天',' 无期限','自定义'];
String startDate = '';
String endDate = '选择周期';
String currentWeek = '请选择';
String ringing = '默认铃声';
int pickDateIndex = 0; // 选择开始时间下标
int pickWeekIndex = 7; // 选择重复下标
int pickDurationIndex = -1; // 选择周期时间下标
int pickEndIndex = 0; // 选择自定义周期下标
int pickHourIndex = 0; // 选择自定义周期下标
int pickMinuteIndex = 0; // 选择自定义周期下标
// List<Map> clockList = [{'showValue': '08:00', 'value': 480}, {'showValue': '09:30', 'value': 570}]; // 提醒闹钟列表
List<Map> clockList = []; // 提醒闹钟列表
List<String> hourList = [];
List<String> minuteList = [];
FixedExtentScrollController startScrollCtr = new FixedExtentScrollController();
FixedExtentScrollController endScrollCtr = new FixedExtentScrollController();
FixedExtentScrollController hourScrollCtr = new FixedExtentScrollController();
FixedExtentScrollController minuteScrollCtr = new FixedExtentScrollController();
// 今天的时间
var today = new DateTime.now();
String formatDate(DateTime date) {
return date.year.toString() + '年' + date.month.toString() + '月' + date.day.toString() + '日 星期' + getWeekday(date.weekday);
}
String getWeekday(int num) {
switch(num) {
case 1:
return '一';
break;
case 2:
return '二';
break;
case 3:
return '三';
break;
case 4:
return '四';
break;
case 5:
return '五';
break;
case 6:
return '六';
break;
default:
return '日';
break;
}
}
void createStartDateList() {
for(int i = 0; i < 90; i++ ) {
var tempDay = today.add(new Duration(days: i));
Map tempObj = {'value': tempDay, 'showValue': formatDate(tempDay)};
startList.add(tempObj);
}
createEndDateList(today);
setState(() {
startDate = formatDate(today);
});
}
void createEndDateList(DateTime start) {
endList = [];
for(int i = 0; i < 366; i++) {
var tempDay = start.add(new Duration(days: i));
Map tempObj = {'value': tempDay, 'showValue': formatDate(tempDay)};
endList.add(tempObj);
}
}
void createHourList() {
for(int i = 0; i < 24; i++) {
hourList.add(i.toString().padLeft(2, '0'));
}
}
void createMinuteList() {
for(int i = 0; i < 60; i++) {
minuteList.add(i.toString().padLeft(2, '0'));
}
}
@override
void initState() {
super.initState();
createStartDateList();
createHourList();
createMinuteList();
}
Iterable<Widget> get startDateItems sync* {
for(int i = 0, length = startList.length; i < length; i++) {
yield Container(
height: ScreenUtil.getInstance().setSize(80),
alignment: Alignment.center,
child: Text(startList[i]['showValue'], style: TextStyle(fontSize: ScreenUtil.getInstance().setSp(36), color: kLingyiText500)),
);
}
}
Iterable<Widget> get endDateItems sync* {
for(int i = 0, length = endList.length; i < length; i++) {
yield Container(
height: ScreenUtil.getInstance().setSize(80),
alignment: Alignment.center,
child: Text(endList[i]['showValue'], style: TextStyle(fontSize: ScreenUtil.getInstance().setSp(36), color: kLingyiText500)),
);
}
}
Iterable<Widget> get hourItems sync* {
for(int i = 0, length = hourList.length; i < length; i++) {
yield Container(
height: ScreenUtil.getInstance().setSize(80),
alignment: Alignment.center,
child: Text(hourList[i], style: TextStyle(fontSize: ScreenUtil.getInstance().setSp(36), color: kLingyiText500)),
);
}
}
Iterable<Widget> get minuteItems sync* {
for(int i = 0, length = minuteList.length; i < length; i++) {
yield Container(
height: ScreenUtil.getInstance().setSize(80),
alignment: Alignment.center,
child: Text(minuteList[i], style: TextStyle(fontSize: ScreenUtil.getInstance().setSp(36), color: kLingyiText500)),
);
}
}
void setCurrentWeek() {
// 判断是否是全选
if(weekList.last['isPick']) {
setState(() {
currentWeek = '每天';
});
}else {
var tempList = [];
weekList.forEach((value) {
if(value['isPick']) {
tempList.add(value['showValue']);
}
});
setState(() {
currentWeek = tempList.isEmpty ? '请选择' : tempList.join(',');
});
}
}
void setEndDate() {
var tempString = '';
switch(pickDurationIndex) {
case 0:
tempString = formatDate(startList[pickDateIndex]['value'].add(new Duration(days: 7)));
break;
case 1:
tempString = formatDate(startList[pickDateIndex]['value'].add(new Duration(days: 30)));
break;
case 2:
tempString = formatDate(startList[pickDateIndex]['value'].add(new Duration(days: 90)));
break;
case 3:
tempString = formatDate(startList[pickDateIndex]['value'].add(new Duration(days: 180)));
break;
case 4:
tempString = formatDate(startList[pickDateIndex]['value'].add(new Duration(days: 365)));
break;
case 5:
tempString = '无期限';
break;
default:
tempString = endList[pickEndIndex]['showValue'];
break;
}
setState(() {
endDate = tempString;
});
}
void showClockPick(int value, {int editIndex=-1}) {
// 初始化
pickHourIndex = 0;
pickMinuteIndex = 0;
int positionHour = value ~/ 60;
int positionMinute = value.remainder(60);
showModalBottomSheet(
context: context,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(ScreenUtil.getInstance().setSize(16)),
topRight: Radius.circular(ScreenUtil.getInstance().setSize(16)),
)
),
builder: (context) {
hourScrollCtr.jumpToItem(positionHour);
minuteScrollCtr.jumpToItem(positionMinute);
return Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Container(
height: ScreenUtil.getInstance().setSize(105),
alignment: Alignment.center,
decoration: BoxDecoration(
color: kLingyiWhite,
border: Border(bottom: BorderSide(color: kLingyiGray, width: ScreenUtil.getInstance().setSize(1)))
),
child: Text('设置提醒', style: TextStyle(fontSize: ScreenUtil.getInstance().setSp(32), color: kLingyiOrange),),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Expanded(
flex: 1,
child: Container(
height: ScreenUtil.getInstance().setSize(480),
child: CupertinoPicker(
itemExtent: ScreenUtil.getInstance().setSize(80),
onSelectedItemChanged: (index) {
pickHourIndex = index;
},
scrollController: hourScrollCtr,
diameterRatio: 720.0,
// 滚筒的曲率,就是弯曲的程度
useMagnifier: true,
magnification: 1.0,
looping: true,
backgroundColor: kLingyiWhite,
offAxisFraction: 100.0,
// 子项的偏移
children: hourItems.toList(),
)
),
),
Expanded(
flex: 1,
child: Container(
height: ScreenUtil.getInstance().setSize(480),
child: CupertinoPicker(
itemExtent: ScreenUtil.getInstance().setSize(80),
onSelectedItemChanged: (index) {
pickMinuteIndex = index;
},
scrollController: minuteScrollCtr,
diameterRatio: 720.0,
// 滚筒的曲率,就是弯曲的程度
useMagnifier: true,
magnification: 1.0,
looping: true,
backgroundColor: kLingyiWhite,
offAxisFraction: 100.0,
// 子项的偏移
children: minuteItems.toList(),
)
),
)
],
),
Container(
height: ScreenUtil.getInstance().setSize(20),
color: kLingyiGray100,
),
Container(
color: kLingyiWhite,
padding: EdgeInsets.fromLTRB(ScreenUtil.getInstance().setSize(36), 0, ScreenUtil.getInstance().setSize(36), 0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Expanded(
flex: 1,
child: GestureDetector(
onTap: () {
Navigator.pop(context);
},
child: Container(
height: ScreenUtil.getInstance().setSize(90),
decoration: BoxDecoration(
border: Border(right: BorderSide(color: kLingyiGray, width: ScreenUtil.getInstance().setSize(1)))
),
alignment: Alignment.center,
child: Text('取消', style: TextStyle(fontSize: ScreenUtil.getInstance().setSp(32), color: kLingyiText100),),
),
)
),
Expanded(
flex: 1,
child: GestureDetector(
onTap: () {
int tempValue = pickHourIndex * 60 + pickMinuteIndex;
for(int i = 0, length = clockList.length; i < length; i++) {
if(clockList[i]['value'] == tempValue) {
showMsg(context, '已设置相同时刻的提醒');
return;
}
}
// 判断是否是编辑
if(editIndex > -1) {
clockList.removeAt(editIndex);
}
Map tempClock = {
'showValue': hourList[pickHourIndex] + ':' + minuteList[pickMinuteIndex],
'value': tempValue
};
clockList.add(tempClock);
// 按小到大排序
sortClock();
Navigator.pop(context);
},
child: Container(
height: ScreenUtil.getInstance().setSize(100),
alignment: Alignment.center,
child: Text('确认', style: TextStyle(fontSize: ScreenUtil.getInstance().setSp(32), color: kLingyiGreen),),
),
)
),
],
),
),
Container(
color: kLingyiWhite,
height: ScreenUtil.bottomBarHeight,
)
],
);
},
);
}
void sortClock() {
if (clockList == null || clockList.isEmpty) return;
clockList.sort((b, a) => b['value'].compareTo(a['value']));
setState(() {});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.option.query['name']!=null?widget.option.query['name']:'吃药'),
leading: goBackArr(context),
actions: <Widget>[
Container(
padding: EdgeInsets.only(right: 20),
alignment: Alignment.center,
child: MaterialButton(
onPressed: () async {
showToast(context, '保存成功', isSuccess: true, callback: () {
Navigator.pop(context);
});
},
color: kLingyiGreen,
elevation: 0,
minWidth: 50,
height: 24,
child: Text('保存',
style: TextStyle(
fontSize: ScreenUtil.getInstance().setSize(24),
color: kLingyiWhite)),
),
),
],
),
body: Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
color: kLingyiGray100,
child: ListView(
children: <Widget>[
Container(
padding: EdgeInsets.only(left: ScreenUtil.getInstance().setSize(36)),
color: kLingyiWhite,
child: Container(
height: ScreenUtil.getInstance().setSize(150),
padding: EdgeInsets.only(right: ScreenUtil.getInstance().setSize(36)),
decoration: BoxDecoration(
border: Border(bottom: BorderSide(color: kLingyiGray, width: ScreenUtil.getInstance().setSize(1)))
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
CircleAvatar(
backgroundColor: kLingyiGray400,
radius: ScreenUtil.getInstance().setSize(45),
backgroundImage: getAssetImage(widget.option.query['icon']!=null?widget.option.query['icon']:'2_health/t_drug.png'),
),
SizedBox(
width: ScreenUtil.getInstance().setSize(520),
child: Text(widget.option.query['name']!=null?widget.option.query['name']:'吃药', style: TextStyle(fontSize: ScreenUtil.getInstance().setSp(32), color: kLingyiText500),),
),
SizedBox(
width: ScreenUtil.getInstance().setSize(30),
)
// nextPageArr()
],
),
)
),
// 开始时间
GestureDetector(
onTap: () {
showModalBottomSheet(
context: context,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(ScreenUtil.getInstance().setSize(16)),
topRight: Radius.circular(ScreenUtil.getInstance().setSize(16)),
)
),
builder: (context) {
startScrollCtr.jumpToItem(pickDateIndex);
return Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Container(
height: ScreenUtil.getInstance().setSize(105),
alignment: Alignment.center,
decoration: BoxDecoration(
color: kLingyiWhite,
border: Border(bottom: BorderSide(color: kLingyiGray, width: ScreenUtil.getInstance().setSize(1)))
),
child: Text('开始时间', style: TextStyle(fontSize: ScreenUtil.getInstance().setSp(32), color: kLingyiOrange),),
),
Container(
height: ScreenUtil.getInstance().setSize(480),
child: CupertinoPicker(
itemExtent: ScreenUtil.getInstance().setSize(80),
onSelectedItemChanged: (index) {
pickDateIndex = index;
},
scrollController: startScrollCtr,
diameterRatio: 720.0,
// 滚筒的曲率,就是弯曲的程度
useMagnifier: true,
magnification: 1.0,
looping: true,
backgroundColor: kLingyiWhite,
offAxisFraction: 100.0,
// 子项的偏移
children: startDateItems.toList(),
)
),
Container(
height: ScreenUtil.getInstance().setSize(20),
color: kLingyiGray100,
),
Container(
color: kLingyiWhite,
padding: EdgeInsets.fromLTRB(ScreenUtil.getInstance().setSize(36), 0, ScreenUtil.getInstance().setSize(36), 0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Expanded(
flex: 1,
child: GestureDetector(
onTap: () {
Navigator.pop(context);
},
child: Container(
height: ScreenUtil.getInstance().setSize(90),
decoration: BoxDecoration(
border: Border(right: BorderSide(color: kLingyiGray, width: ScreenUtil.getInstance().setSize(1)))
),
alignment: Alignment.center,
child: Text('取消', style: TextStyle(fontSize: ScreenUtil.getInstance().setSp(32), color: kLingyiText100),),
),
)
),
Expanded(
flex: 1,
child: GestureDetector(
onTap: () {
setState(() {
startDate = startList[pickDateIndex]['showValue'];
});
createEndDateList(startList[pickDateIndex]['value']);
Navigator.pop(context);
},
child: Container(
height: ScreenUtil.getInstance().setSize(100),
alignment: Alignment.center,
child: Text('确认', style: TextStyle(fontSize: ScreenUtil.getInstance().setSp(32), color: kLingyiGreen),),
),
)
),
],
),
),
Container(
color: kLingyiWhite,
height: ScreenUtil.bottomBarHeight,
)
],
);
},
);
},
child: Container(
padding: EdgeInsets.only(left: ScreenUtil.getInstance().setSize(36)),
color: kLingyiWhite,
child: Container(
height: ScreenUtil.getInstance().setSize(100),
padding: EdgeInsets.only(right: ScreenUtil.getInstance().setSize(36)),
decoration: BoxDecoration(
border: Border(bottom: BorderSide(color: kLingyiGray, width: ScreenUtil.getInstance().setSize(1)))
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
SizedBox(
width: ScreenUtil.getInstance().setSize(150),
child: Text('开始时间', style: TextStyle(fontSize: ScreenUtil.getInstance().setSp(28), color: kLingyiText500),),
),
SizedBox(
width: ScreenUtil.getInstance().setSize(460),
child: Text(startDate, style: TextStyle(fontSize: ScreenUtil.getInstance().setSp(32), color: kLingyiOrange), textAlign: TextAlign.right,),
),
nextPageArr()
],
),
)
),
),
// 结束时间
GestureDetector(
onTap: () {
showModalBottomSheet(
context: context,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(ScreenUtil.getInstance().setSize(16)),
topRight: Radius.circular(ScreenUtil.getInstance().setSize(16)),
)
),
builder: (context) {
return StatefulBuilder(
builder: (BuildContext context, setState) {
endScrollCtr.jumpToItem(pickEndIndex);
return Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Container(
height: ScreenUtil.getInstance().setSize(105),
alignment: Alignment.center,
decoration: BoxDecoration(
color: kLingyiWhite,
border: Border(bottom: BorderSide(color: kLingyiGray, width: ScreenUtil.getInstance().setSize(1)))
),
child: Text('结束时间', style: TextStyle(fontSize: ScreenUtil.getInstance().setSp(32), color: kLingyiOrange),),
),
Container(
width: MediaQuery.of(context).size.height,
height: ScreenUtil.getInstance().setSize(240),
color: kLingyiWhite,
padding: EdgeInsets.fromLTRB(ScreenUtil.getInstance().setSize(36), ScreenUtil.getInstance().setSize(30), ScreenUtil.getInstance().setSize(36), ScreenUtil.getInstance().setSize(30)),
child: GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 4,
childAspectRatio: 2,
crossAxisSpacing: 20,
mainAxisSpacing: ScreenUtil.getInstance().setSize(30),
),
itemCount: durationList.length,
itemBuilder: (BuildContext context, int index) {
return GestureDetector(
onTap: () {
// setPickDurationIndex(index);
setState(() {
pickDurationIndex = index;
});
},
child: Container(
height: ScreenUtil.getInstance().setSize(72),
width: ScreenUtil.getInstance().setSize(145),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(ScreenUtil.getInstance().setSize(36)),
border: Border.all(color: (pickDurationIndex == index) ? kLingyiGreen : kLingyiGray, width: ScreenUtil.getInstance().setSize(1)),
color: (pickDurationIndex == index) ? kLingyiGreen : kLingyiWhite
),
child: Stack(
alignment: Alignment.center,
children: <Widget>[
Text(durationList[index], style: TextStyle(fontSize: ScreenUtil.getInstance().setSp(32), color: (pickDurationIndex == index) ? kLingyiWhite : kLingyiText500),)
],
),
)
);
}
)
),
Offstage(
offstage: pickDurationIndex != 6,
child: Container(
height: ScreenUtil.getInstance().setSize(320),
child: CupertinoPicker(
itemExtent: ScreenUtil.getInstance().setSize(80),
onSelectedItemChanged: (index) {
pickEndIndex = index;
},
scrollController: endScrollCtr,
diameterRatio: 720.0,
// 滚筒的曲率,就是弯曲的程度
useMagnifier: true,
magnification: 1.0,
looping: true,
backgroundColor: kLingyiWhite,
offAxisFraction: 100.0,
// 子项的偏移
children: endDateItems.toList(),
)
),
),
Container(
height: ScreenUtil.getInstance().setSize(20),
color: kLingyiGray100,
),
Container(
color: kLingyiWhite,
padding: EdgeInsets.fromLTRB(ScreenUtil.getInstance().setSize(36), 0, ScreenUtil.getInstance().setSize(36), 0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Expanded(
flex: 1,
child: GestureDetector(
onTap: () {
Navigator.pop(context);
},
child: Container(
height: ScreenUtil.getInstance().setSize(90),
decoration: BoxDecoration(
border: Border(right: BorderSide(color: kLingyiGray, width: ScreenUtil.getInstance().setSize(1)))
),
alignment: Alignment.center,
child: Text('取消', style: TextStyle(fontSize: ScreenUtil.getInstance().setSp(32), color: kLingyiText100),),
),
)
),
Expanded(
flex: 1,
child: GestureDetector(
onTap: () {
setEndDate();
Navigator.pop(context);
},
child: Container(
height: ScreenUtil.getInstance().setSize(100),
alignment: Alignment.center,
child: Text('确认', style: TextStyle(fontSize: ScreenUtil.getInstance().setSp(32), color: kLingyiGreen),),
),
)
),
],
),
),
Container(
color: kLingyiWhite,
height: ScreenUtil.bottomBarHeight,
)
],
);
},
);
},
);
},
child: Container(
padding: EdgeInsets.only(left: ScreenUtil.getInstance().setSize(36)),
color: kLingyiWhite,
child: Container(
height: ScreenUtil.getInstance().setSize(100),
padding: EdgeInsets.only(right: ScreenUtil.getInstance().setSize(36)),
decoration: BoxDecoration(
border: Border(bottom: BorderSide(color: kLingyiGray, width: ScreenUtil.getInstance().setSize(1)))
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
SizedBox(
width: ScreenUtil.getInstance().setSize(150),
child: Text('结束时间', style: TextStyle(fontSize: ScreenUtil.getInstance().setSp(28), color: kLingyiText500),),
),
SizedBox(
width: ScreenUtil.getInstance().setSize(460),
child: Text(endDate, style: TextStyle(fontSize: ScreenUtil.getInstance().setSp(32), color: kLingyiOrange), textAlign: TextAlign.right,),
),
nextPageArr()
],
),
),
),
),
// 重复
GestureDetector(
onTap: () {
showModalBottomSheet(
context: context,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(ScreenUtil.getInstance().setSize(16)),
topRight: Radius.circular(ScreenUtil.getInstance().setSize(16)),
)
),
builder: (context) {
return StatefulBuilder(
builder: (BuildContext context, setState) {
return Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Container(
height: ScreenUtil.getInstance().setSize(105),
alignment: Alignment.center,
decoration: BoxDecoration(
color: kLingyiWhite,
border: Border(bottom: BorderSide(color: kLingyiGray, width: ScreenUtil.getInstance().setSize(1)))
),
child: Text('任务频率', style: TextStyle(fontSize: ScreenUtil.getInstance().setSp(32), color: kLingyiOrange),),
),
Container(
width: MediaQuery.of(context).size.height,
height: ScreenUtil.getInstance().setSize(240),
color: kLingyiWhite,
padding: EdgeInsets.fromLTRB(ScreenUtil.getInstance().setSize(36), ScreenUtil.getInstance().setSize(30), ScreenUtil.getInstance().setSize(36), ScreenUtil.getInstance().setSize(30)),
child: GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 4,
childAspectRatio: 2,
crossAxisSpacing: 20,
mainAxisSpacing: ScreenUtil.getInstance().setSize(30),
),
itemCount: weekList.length,
itemBuilder: (BuildContext context, int index) {
return GestureDetector(
onTap: () {
weekList[index]['isPick'] = !weekList[index]['isPick'];
if(index == weekList.length-1) {
// 全选与反选
for(int i = 0, length = weekList.length-1; i < length; i++) {
weekList[i]['isPick'] = weekList[index]['isPick'];
}
}else {
// 判断是否全选
if(weekList[index]['isPick']) {
weekList.last['isPick'] = true;
for(int i = 0, length = weekList.length-1; i < length; i++) {
if(!weekList[i]['isPick']) {
weekList.last['isPick'] = false;
break;
}
}
}else {
weekList.last['isPick'] = false;
}
}
setState(() {});
},
child: Container(
height: ScreenUtil.getInstance().setSize(72),
padding: EdgeInsets.fromLTRB(ScreenUtil.getInstance().setSize(36), 0, ScreenUtil.getInstance().setSize(36), 0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(ScreenUtil.getInstance().setSize(36)),
border: Border.all(color: weekList[index]['isPick'] ? kLingyiGreen : kLingyiGray, width: ScreenUtil.getInstance().setSize(1)),
color: weekList[index]['isPick'] ? kLingyiGreen : kLingyiWhite
),
child: Stack(
alignment: Alignment.center,
children: <Widget>[
Text(weekList[index]['showValue'], style: TextStyle(fontSize: ScreenUtil.getInstance().setSp(32), color: weekList[index]['isPick'] ? kLingyiWhite : kLingyiText500),)
],
),
)
);
}
)
),
Container(
height: ScreenUtil.getInstance().setSize(100),
color: kLingyiGray100,
alignment: Alignment.center,
child: RichText(
text: TextSpan(
children: [
TextSpan(
text: '由',
style: TextStyle(fontSize: ScreenUtil.getInstance().setSp(32), color: kLingyiText100),
),
TextSpan(
text: startDate,
style: TextStyle(fontSize: ScreenUtil.getInstance().setSp(32), color: kLingyiOrange),
),
TextSpan(
text: '开始,每天坚持',
style: TextStyle(fontSize: ScreenUtil.getInstance().setSp(32), color: kLingyiText100),
),
]
),
),
),
Container(
color: kLingyiWhite,
padding: EdgeInsets.fromLTRB(ScreenUtil.getInstance().setSize(36), 0, ScreenUtil.getInstance().setSize(36), 0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Expanded(
flex: 1,
child: GestureDetector(
onTap: () {
Navigator.pop(context);
},
child: Container(
height: ScreenUtil.getInstance().setSize(90),
decoration: BoxDecoration(
border: Border(right: BorderSide(color: kLingyiGray, width: ScreenUtil.getInstance().setSize(1)))
),
alignment: Alignment.center,
child: Text('取消', style: TextStyle(fontSize: ScreenUtil.getInstance().setSp(32), color: kLingyiText100),),
),
)
),
Expanded(
flex: 1,
child: GestureDetector(
onTap: () {
setCurrentWeek();
Navigator.pop(context);
},
child: Container(
height: ScreenUtil.getInstance().setSize(100),
alignment: Alignment.center,
child: Text('确认', style: TextStyle(fontSize: ScreenUtil.getInstance().setSp(32), color: kLingyiGreen),),
),
)
),
],
),
),
Container(
color: kLingyiWhite,
height: ScreenUtil.bottomBarHeight,
)
],
);
}
);
},
);
},
child: Container(
padding: EdgeInsets.only(left: ScreenUtil.getInstance().setSize(36)),
color: kLingyiWhite,
child: Container(
height: ScreenUtil.getInstance().setSize(100),
padding: EdgeInsets.only(right: ScreenUtil.getInstance().setSize(36)),
decoration: BoxDecoration(
border: Border(bottom: BorderSide(color: kLingyiGray, width: ScreenUtil.getInstance().setSize(1)))
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
SizedBox(
width: ScreenUtil.getInstance().setSize(150),
child: Text('重复', style: TextStyle(fontSize: ScreenUtil.getInstance().setSp(28), color: kLingyiText500),),
),
SizedBox(
width: ScreenUtil.getInstance().setSize(460),
child: Text(currentWeek, style: TextStyle(fontSize: ScreenUtil.getInstance().setSp(32), color: kLingyiText500), textAlign: TextAlign.right,),
),
nextPageArr()
],
),
),
),
),
// 提醒
Container(
padding: EdgeInsets.only(left: ScreenUtil.getInstance().setSize(36)),
color: kLingyiWhite,
child: Container(
height: ScreenUtil.getInstance().setSize(100),
padding: EdgeInsets.only(right: ScreenUtil.getInstance().setSize(36)),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
SizedBox(
width: ScreenUtil.getInstance().setSize(150),
child: Text('提醒', style: TextStyle(fontSize: ScreenUtil.getInstance().setSp(28), color: kLingyiText500),),
),
CupertinoSwitch(
value: isWork,
onChanged: (value) async {
setState(() {
isWork = value;
});
}
),
],
),
),
),
Container(
padding: EdgeInsets.only(left: ScreenUtil.getInstance().setSize(36)),
color: kLingyiWhite,
child: Container(
height: ScreenUtil.getInstance().setSize(clockList.length < 5 ? 120 : 240),
padding: EdgeInsets.only(right: ScreenUtil.getInstance().setSize(12)),
decoration: BoxDecoration(
border: Border(bottom: BorderSide(color: kLingyiGray, width: ScreenUtil.getInstance().setSize(1)))
),
child: GridView.builder(
padding: EdgeInsets.only(right: ScreenUtil.getInstance().setSize(24)),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 5,
childAspectRatio: 2,
crossAxisSpacing: 10,
mainAxisSpacing: ScreenUtil.getInstance().setSize(30),
),
itemCount: clockList.length+1,
itemBuilder: (BuildContext context, int index) {
if(index < clockList.length) {
return GestureDetector(
onTap: () {
showClockPick(clockList[index]['value'], editIndex: index);
},
child: Container(
padding: EdgeInsets.only(top: ScreenUtil.getInstance().setSize(12)),
width: ScreenUtil.getInstance().setSize(120),
child: Stack(
overflow: Overflow.visible,
children: <Widget>[
Positioned(
left: 0,
top: 0,
width: ScreenUtil.getInstance().setSize(120),
height: ScreenUtil.getInstance().setSize(76),
child: Container(
width: ScreenUtil.getInstance().setSize(120),
height: ScreenUtil.getInstance().setSize(76),
decoration: BoxDecoration(
color: Color(0xfff5f5f5),
borderRadius: BorderRadius.circular(ScreenUtil.getInstance().setSize(8))
),
child: Stack(
alignment: Alignment.center,
children: <Widget>[
Text(clockList[index]['showValue'], style: TextStyle(fontSize: ScreenUtil.getInstance().setSp(32), color: kLingyiText500),)
],
),
),
),
Positioned(
right: ScreenUtil.getInstance().setSize(-12),
top: ScreenUtil.getInstance().setSize(-12),
width: ScreenUtil.getInstance().setSize(36),
height: ScreenUtil.getInstance().setSize(36),
child: GestureDetector(
onTap: () {
// 删除对应闹钟
clockList.removeAt(index);
setState(() {});
},
child: CircleAvatar(
radius: ScreenUtil.getInstance().setSize(36),
backgroundColor: kLingyiGray300,
backgroundImage: getAssetImage('2_health/s_delete.png'),
)
),
)
],
),
)
);
}else {
return Offstage(
offstage: clockList.length > 9,
child: GestureDetector(
onTap: () {
showClockPick(0);
},
child: Container(
padding: EdgeInsets.only(top: ScreenUtil.getInstance().setSize(12)),
width: ScreenUtil.getInstance().setSize(120),
child: Stack(
overflow: Overflow.visible,
children: <Widget>[
Positioned(
left: 0,
top: 0,
width: ScreenUtil.getInstance().setSize(120),
height: ScreenUtil.getInstance().setSize(76),
child: Container(
width: ScreenUtil.getInstance().setSize(120),
height: ScreenUtil.getInstance().setSize(76),
decoration: BoxDecoration(
color: Color(0xfff5f5f5),
borderRadius: BorderRadius.circular(ScreenUtil.getInstance().setSize(8))
),
child: Stack(
alignment: Alignment.center,
children: <Widget>[
Image(
width: ScreenUtil.getInstance().setSize(32),
height: ScreenUtil.getInstance().setSize(32),
fit: BoxFit.cover,
image: getAssetImage('2_health/i_add.png'),
)
],
),
),
),
],
),
)
)
);
}
}
)
),
),
// 提醒音
GestureDetector(
onTap: () async{
var res = await Navigator.of(context).push(
MaterialPageRoute(builder: (BuildContext context) {
return AppRoute.getPage('page://health/ringing', {});
})
);
if (res != null) {
print(res['info']);
setState(() {
ringing = res['info'];
});
}
},
child: Container(
padding: EdgeInsets.only(left: ScreenUtil.getInstance().setSize(36)),
color: kLingyiWhite,
child: Container(
height: ScreenUtil.getInstance().setSize(100),
padding: EdgeInsets.only(right: ScreenUtil.getInstance().setSize(36)),
decoration: BoxDecoration(
border: Border(bottom: BorderSide(color: kLingyiGray, width: ScreenUtil.getInstance().setSize(1)))
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
SizedBox(
width: ScreenUtil.getInstance().setSize(150),
child: Text('提醒音', style: TextStyle(fontSize: ScreenUtil.getInstance().setSp(28), color: kLingyiText500),),
),
SizedBox(
width: ScreenUtil.getInstance().setSize(460),
child: Text(ringing, style: TextStyle(fontSize: ScreenUtil.getInstance().setSp(32), color: kLingyiText500), textAlign: TextAlign.right,),
),
nextPageArr()
],
),
),
),
)
// 更多提醒方式
// Container(
// padding: EdgeInsets.only(left: ScreenUtil.getInstance().setSize(36)),
// color: kLingyiWhite,
// child: Container(
// height: ScreenUtil.getInstance().setSize(100),
// padding: EdgeInsets.only(right: ScreenUtil.getInstance().setSize(36)),
// decoration: BoxDecoration(
// border: Border(bottom: BorderSide(color: kLingyiGray, width: ScreenUtil.getInstance().setSize(1)))
// ),
// child: Row(
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
// children: <Widget>[
// SizedBox(
// width: ScreenUtil.getInstance().setSize(200),
// child: Text('更多提醒方式', style: TextStyle(fontSize: ScreenUtil.getInstance().setSp(28), color: kLingyiText500),),
// ),
// SizedBox(
// width: ScreenUtil.getInstance().setSize(410),
// child: Row(
// mainAxisAlignment: MainAxisAlignment.end,
// children: <Widget>[
// ClipRRect(
// borderRadius: BorderRadius.circular(ScreenUtil.getInstance().setSize(8)),
// child: Image(
// width: ScreenUtil.getInstance().setSize(48),
// height: ScreenUtil.getInstance().setSize(48),
// image: getAssetImage('default.png'),
// fit: BoxFit.cover,
// ),
// ),
// SizedBox(width: ScreenUtil.getInstance().setSize(24),),
// ClipRRect(
// borderRadius: BorderRadius.circular(ScreenUtil.getInstance().setSize(8)),
// child: Image(
// width: ScreenUtil.getInstance().setSize(48),
// height: ScreenUtil.getInstance().setSize(48),
// image: getAssetImage('default.png'),
// fit: BoxFit.cover,
// ),
// ),
// SizedBox(width: ScreenUtil.getInstance().setSize(24),),
// ClipRRect(
// borderRadius: BorderRadius.circular(ScreenUtil.getInstance().setSize(8)),
// child: Image(
// width: ScreenUtil.getInstance().setSize(48),
// height: ScreenUtil.getInstance().setSize(48),
// image: getAssetImage('default.png'),
// fit: BoxFit.cover,
// ),
// ),
// ],
// ),
// ),
// nextPageArr()
// ],
// ),
// ),
// )
],
)
)
);
}
}
封装空列表呈现组件
import 'package:flutter/material.dart';
import 'package:lingyi/config/color.dart';
import 'package:lingyi/util/common.dart';
class Nothing extends StatelessWidget {
final String title;
final double height;
final Color bgColor;
final bool isLoading;
Nothing(this.title, {this.height, this.bgColor, this.isLoading=false});
@override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.only(bottom: ScreenUtil.getInstance().setSize(100)),
width: MediaQuery.of(context).size.width,
height: height ?? MediaQuery.of(context).size.height,
decoration: BoxDecoration(
color: bgColor ?? kLingyiGray100
),
alignment: Alignment.center,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
isLoading ? Image(image: getAssetImage('1_circle/loading.png'), width: ScreenUtil.getInstance().setSize(380), fit: BoxFit.fitWidth,)
: Image(image: getAssetImage('5_public/default.png'), width: ScreenUtil.getInstance().setSize(420), fit: BoxFit.fitWidth,),
SizedBox(width: ScreenUtil.getInstance().setSize(30)),
Offstage(
offstage: isLoading,
child: Text(title, style: TextStyle(fontSize: ScreenUtil.getInstance().setSp(28), color: kLingyiText100),)
)
],
),
);
}
}
安全区域的使用
1. 弹窗使用ScreenUtil.bottomBarHeight在底部增加高度
2. 使用SafeArea组件包括整个应用
根页面返回键退出App处理
使用 WillPopScope 组件包括入口组件
Future<bool> _onWillPop() async {
ShowAlert.show(context, '确定退出应用吗?', onConfirm: () {
SystemNavigator.pop();
});
return false;
}
webView 页面友好处理
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'package:annotation_route/route.dart';
import 'package:lingyi/config/color.dart';
@ARoute(url: 'page://webview')
class Webview extends StatefulWidget {
final dynamic option;
Webview(this.option);
@override
WebviewState createState() => WebviewState();
}
class WebviewState extends State<Webview> {
bool isLoading = true;
@override
Widget build(BuildContext context) {
String url = widget.option.query['url'];
String title = widget.option.query['title'];
return Scaffold(
appBar: AppBar(
title: Text(title),
leading: goBackArr(context),
bottom: PreferredSize(
preferredSize: Size.fromHeight(ScreenUtil.getInstance().setSize(4)),
child: Offstage(
offstage: !isLoading,
child: SizedBox(
height: ScreenUtil.getInstance().setSize(4),
width: MediaQuery.of(context).size.width,
child: LinearProgressIndicator(),
),
),
),
),
body: WebView(
onWebViewCreated: (WebViewController web) {
setState(() {
isLoading = true;
});
},
onPageFinished: (String value) {
setState(() {
isLoading = false;
});
},
initialUrl: url,
javascriptMode: JavascriptMode.unrestricted,
),
);
}
}
pdf 预览功能
import 'dart:async';
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_full_pdf_viewer/full_pdf_viewer_scaffold.dart';
import 'package:path_provider/path_provider.dart';
import 'package:annotation_route/route.dart';
import 'package:lingyi/config/color.dart';
import 'package:lingyi/util/common.dart';
// import 'package:flutter/services.dart' show rootBundle;
// import 'dart:typed_data';
@ARoute(url: 'page://pdfview')
class Pdfview extends StatefulWidget {
final dynamic option;
Pdfview(this.option);
@override
PdfviewState createState() => new PdfviewState();
}
class PdfviewState extends State<Pdfview> {
String pathPDF = "";
@override
void initState() {
super.initState();
createFileOfPdfUrl().then((f) {
print(f.toString());
setState(() {
pathPDF = f.path;
print(pathPDF);
});
});
}
Future<File> createFileOfPdfUrl() async {
final url = "http://africau.edu/images/default/sample.pdf";
final filename = url.substring(url.lastIndexOf("/") + 1);
var request = await HttpClient().getUrl(Uri.parse(url));
var response = await request.close();
var bytes = await consolidateHttpClientResponseBytes(response);
String dir = (await getApplicationDocumentsDirectory()).path;
File file = new File('$dir/$filename');
await file.writeAsBytes(bytes);
return file;
}
// @override
// void initState() {
// super.initState();
// print('init');
// printFile();
// createFileOfPdfUrl().then((f) {
// setState(() {
// pathPDF = f.path;
// print(pathPDF);
// });
// });
// }
// void printFile() async {
// var filebd = await rootBundle.load("assets/data/cannon.pdf");
// print(filebd.runtimeType);
// }
// Future<void> writeToFile(ByteData data, String path) {
// final buffer = data.buffer;
// return new File(path).writeAsBytes(
// buffer.asUint8List(data.offsetInBytes, data.lengthInBytes));
// }
// Future<File> createFileOfPdfUrl() async {
// final filename = 'test.pdf';
// var bytes = await rootBundle.load("assets/data/cannon.pdf");
// String dir = (await getApplicationDocumentsDirectory()).path;
// writeToFile(bytes,'$dir/$filename');
// File file = new File('$dir/$filename');
// return file;
// }
@override
Widget build(BuildContext context) {
return pathPDF.isEmpty ? Scaffold(
appBar: AppBar(
title: Text("Document"),
),
body: Container(
padding: EdgeInsets.only(bottom: ScreenUtil.getInstance().setSize(100)),
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
decoration: BoxDecoration(
color: kLingyiGray100
),
alignment: Alignment.center,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Image(image: getAssetImage('5_public/default.png'), width: ScreenUtil.getInstance().setSize(420), fit: BoxFit.fitWidth,),
SizedBox(width: ScreenUtil.getInstance().setSize(30)),
Text('加载中...', style: TextStyle(fontSize: ScreenUtil.getInstance().setSp(28), color: kLingyiText100),)
],
),
)
) : PDFViewerScaffold(
appBar: AppBar(
title: Text("Document"),
),
path: pathPDF
);
}
}