Files
tuiche/lib/pages/common/selectDialog.dart
2025-06-03 09:00:01 +08:00

938 lines
36 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import 'package:ef/ef.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:vbvs_app/common/color/appConstants.dart';
import 'package:vbvs_app/common/util/FitTool.dart';
import 'package:vbvs_app/common/util/MyUtils.dart';
import 'package:vbvs_app/component/base/SleepCalendarWidget.dart';
import 'package:vbvs_app/controller/device/device_calibration_controller.dart';
import 'package:vbvs_app/controller/theme_controller/ThemeController.dart';
getOnePicker(context, List arr, int checkIndex, Function onSelectedItemChanged,
{bool looping = false}) {
ThemeController themeController = Get.find();
return CupertinoPicker(
key: UniqueKey(),
useMagnifier: false,
itemExtent: 80.rpx,
magnification: 1,
diameterRatio: 3,
squeeze: 1,
looping: looping,
scrollController: FixedExtentScrollController(initialItem: checkIndex),
selectionOverlay: Container(),
onSelectedItemChanged: (int value) {
// print("$value");
onSelectedItemChanged.call(value);
},
children: [
...List.generate(arr.length, (index) {
return Container(
alignment: Alignment.center,
width: 400.rpx,
decoration: BoxDecoration(
border: Border(
bottom: index != arr.length
? BorderSide(
color: stringToColor("#8D95B0"),
)
: BorderSide.none,
),
),
child: Text("${arr[index]}",
style: FlutterFlowTheme.of(context).bodyMedium.override(
fontFamily: 'Readex Pro',
color: themeController.currentColor.sc3,
letterSpacing: 0,
fontSize: 30.rpx)),
);
})
],
);
}
Future showDateSelectionDialog(BuildContext context,
{required DateTime checkDate,
Function? checkChange,
String title = "选择生日"}) {
ThemeController themeController = Get.find();
Color checkColor = stringToColor("#D3B684");
List years = [], months = [], days = [];
var days_select = [].obs;
int day_len = 31;
int year = DateTime.now().year;
for (var i = 0; i < 100; i++) {
years.insert(0, year - i);
}
for (var i = 1; i < 13; i++) {
months.add(i);
}
for (var i = 1; i < 32; i++) {
days.add(i);
}
int yearIndex = years.lastIndexOf(checkDate.year);
int monthIndex = months.lastIndexOf(checkDate.month);
day_len = DateTime.fromMillisecondsSinceEpoch(
DateTime(years[yearIndex], months[monthIndex] + 1)
.millisecondsSinceEpoch -
1000)
.day;
days_select.value = days.sublist(0, day_len);
int dayIndex = days.lastIndexOf(checkDate.day);
return showDialog(
// barrierColor: stringToColor("#000320"),
context: context,
barrierDismissible: true, // 点击对话框外部可关闭
builder: (BuildContext context) {
return Stack(
children: [
Positioned(
bottom: 0, // 控制弹窗距离顶部的位置
left: 0,
right: 0,
child: Material(
color: Colors.transparent,
child: Dialog(
backgroundColor: stringToColor("#182B7C"),
insetPadding: EdgeInsets.zero,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(0),
),
child: Container(
width: double.infinity,
padding: EdgeInsets.fromLTRB(30.rpx, 10.rpx, 30.rpx, 90.rpx),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Container(
alignment: Alignment.centerLeft,
height: 60.rpx,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
"$title",
style: FlutterFlowTheme.of(context)
.bodyMedium
.override(
fontFamily: 'Readex Pro',
color: themeController.currentColor.sc3,
letterSpacing: 0,
fontSize: 30.rpx),
),
closeIconWhite
],
),
),
Container(
height: 240.rpx,
margin: EdgeInsets.only(top: 60.rpx, bottom: 60.rpx),
padding: EdgeInsets.only(left: 30.rpx, right: 30.rpx),
child: Row(
children: [
Expanded(
child: Container(
padding: EdgeInsets.only(
left: 40.rpx, right: 30.rpx),
child: getOnePicker(context, years, yearIndex,
(d) {
yearIndex = d;
dayIndex = 0;
day_len = DateTime.fromMillisecondsSinceEpoch(
DateTime(years[yearIndex],
months[monthIndex] + 1)
.millisecondsSinceEpoch -
1000)
.day;
days_select.value = days.sublist(0, day_len);
}),
),
),
Container(
child: Text(
"",
style: FlutterFlowTheme.of(context)
.bodyMedium
.override(
fontFamily: 'Readex Pro',
color: themeController.currentColor.sc3,
letterSpacing: 0,
fontSize: 30.rpx),
),
),
Expanded(
child: Container(
padding: EdgeInsets.only(
left: 30.rpx, right: 30.rpx),
child: getOnePicker(context, months, monthIndex,
(d) {
monthIndex = d;
dayIndex = 0;
day_len = DateTime.fromMillisecondsSinceEpoch(
DateTime(years[yearIndex],
months[monthIndex] + 1)
.millisecondsSinceEpoch -
1000)
.day;
days_select.value = days.sublist(0, day_len);
}),
),
),
Container(
child: Text(
"",
style: FlutterFlowTheme.of(context)
.bodyMedium
.override(
fontFamily: 'Readex Pro',
color: themeController.currentColor.sc3,
letterSpacing: 0,
fontSize: 30.rpx),
),
),
Expanded(
child: Container(
padding: EdgeInsets.only(
left: 30.rpx, right: 40.rpx),
child: Obx(
() {
// print("${dayIndex} ${day_len}");
return getOnePicker(
context,
days_select,
dayIndex,
(d) {
dayIndex = d;
},
);
},
),
),
),
Container(
child: Text(
"",
style: FlutterFlowTheme.of(context)
.bodyMedium
.override(
fontFamily: 'Readex Pro',
color: themeController.currentColor.sc3,
letterSpacing: 0,
fontSize: 30.rpx),
),
),
],
),
),
InkWell(
onTap: () {
checkChange?.call(DateTime(years[yearIndex],
months[monthIndex], days[dayIndex]));
Get.back();
},
child: Container(
height: 68.rpx,
alignment: Alignment.center,
decoration: BoxDecoration(
color: stringToColor("#D3B684"),
borderRadius: BorderRadius.circular(10.rpx),
),
child: Text(
"确定",
style: FlutterFlowTheme.of(context)
.bodyMedium
.override(
fontFamily: 'Readex Pro',
color: themeController.currentColor.sc3,
letterSpacing: 0,
fontSize: 30.rpx),
),
),
)
],
),
),
),
),
),
],
);
},
);
}
Future showDayTimeSelectionDialog(BuildContext context,
{required List<int> dayTimeArr, Function? checkChange, String title = ""}) {
ThemeController themeController = Get.find();
Color checkColor = stringToColor("#D3B684");
List hours = [], minutes = [];
for (var i = 0; i < 24; i++) {
hours.add(i);
}
for (var i = 0; i < 60; i++) {
minutes.add(i);
}
int hoursIndex = hours.lastIndexOf(dayTimeArr[0]);
int minutesIndex = minutes.lastIndexOf(dayTimeArr[1]);
return showDialog(
// barrierColor: stringToColor("#000320"),
context: context,
barrierDismissible: true, // 点击对话框外部可关闭
builder: (BuildContext context) {
return Stack(
children: [
Positioned(
bottom: 0, // 控制弹窗距离顶部的位置
left: 0,
right: 0,
child: Material(
color: Colors.transparent,
child: Dialog(
backgroundColor: stringToColor("#182B7C"),
insetPadding: EdgeInsets.zero,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(0),
),
child: Container(
width: double.infinity,
padding: EdgeInsets.fromLTRB(30.rpx, 10.rpx, 30.rpx, 90.rpx),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Container(
alignment: Alignment.centerLeft,
height: 60.rpx,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
"$title",
style: FlutterFlowTheme.of(context)
.bodyMedium
.override(
fontFamily: 'Readex Pro',
color: themeController.currentColor.sc3,
letterSpacing: 0,
fontSize: 30.rpx),
),
closeIconWhite
],
),
),
Container(
height: 240.rpx,
margin: EdgeInsets.only(top: 60.rpx, bottom: 60.rpx),
padding: EdgeInsets.only(left: 30.rpx, right: 30.rpx),
child: Row(
children: [
Expanded(
child: Container(
padding: EdgeInsets.only(
left: 40.rpx, right: 30.rpx),
child: getOnePicker(context, hours, hoursIndex,
(d) {
hoursIndex = d;
}),
),
),
Container(
child: Text(
"",
style: FlutterFlowTheme.of(context)
.bodyMedium
.override(
fontFamily: 'Readex Pro',
color: themeController.currentColor.sc3,
letterSpacing: 0,
fontSize: 30.rpx),
),
),
Expanded(
child: Container(
padding: EdgeInsets.only(
left: 30.rpx, right: 30.rpx),
child: getOnePicker(
context, minutes, minutesIndex, (d) {
minutesIndex = d;
}),
),
),
Container(
child: Text(
"",
style: FlutterFlowTheme.of(context)
.bodyMedium
.override(
fontFamily: 'Readex Pro',
color: themeController.currentColor.sc3,
letterSpacing: 0,
fontSize: 30.rpx),
),
),
],
),
),
InkWell(
onTap: () {
checkChange?.call(
[hours[hoursIndex], minutes[minutesIndex]]);
Get.back();
},
child: Container(
height: 68.rpx,
alignment: Alignment.center,
decoration: BoxDecoration(
color: stringToColor("#D3B684"),
borderRadius: BorderRadius.circular(10.rpx),
),
child: Text(
"确定",
style: FlutterFlowTheme.of(context)
.bodyMedium
.override(
fontFamily: 'Readex Pro',
color: themeController.currentColor.sc3,
letterSpacing: 0,
fontSize: 30.rpx),
),
),
)
],
),
),
),
),
),
],
);
},
);
}
Future showOneSelectionDialog(BuildContext context,
{required List arr,
int checkIndex = 0,
Function? checkChange,
String title = "选择性别"}) {
ThemeController themeController = Get.find();
Color checkColor = stringToColor("#D3B684");
return showDialog(
// barrierColor: stringToColor("#000320"),
context: context,
barrierDismissible: true, // 点击对话框外部可关闭
builder: (BuildContext context) {
return Stack(
children: [
Positioned(
bottom: 0, // 控制弹窗距离顶部的位置
left: 0,
right: 0,
child: Material(
color: Colors.transparent,
child: Dialog(
backgroundColor: stringToColor("#182B7C"),
insetPadding: EdgeInsets.zero,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(0),
),
child: Container(
width: double.infinity,
padding: EdgeInsets.fromLTRB(30.rpx, 10.rpx, 30.rpx, 90.rpx),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Container(
alignment: Alignment.centerLeft,
height: 60.rpx,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
"$title",
style: FlutterFlowTheme.of(context)
.bodyMedium
.override(
fontFamily: 'Readex Pro',
color: themeController.currentColor.sc3,
letterSpacing: 0,
fontSize: 30.rpx),
),
closeIconWhite
],
),
),
Container(
height: 240.rpx,
alignment: Alignment.center,
margin: EdgeInsets.only(top: 60.rpx, bottom: 60.rpx),
padding: EdgeInsets.only(left: 30.rpx, right: 30.rpx),
child: Container(
width: 400.rpx,
child:
getOnePicker(context, arr, checkIndex, (index) {
checkIndex = index;
}),
)),
InkWell(
onTap: () {
checkChange?.call(checkIndex);
Get.back();
},
child: Container(
height: 68.rpx,
alignment: Alignment.center,
decoration: BoxDecoration(
color: stringToColor("#D3B684"),
borderRadius: BorderRadius.circular(10.rpx),
),
child: Text(
"确定",
style: FlutterFlowTheme.of(context)
.bodyMedium
.override(
fontFamily: 'Readex Pro',
color: themeController.currentColor.sc3,
letterSpacing: 0,
fontSize: 30.rpx),
),
),
)
],
),
),
),
),
),
],
);
},
);
}
enum ConfirmDialogIcon {
none,
danger,
success,
warn;
get uname {
String v = "";
switch (this) {
case ConfirmDialogIcon.danger:
v = "danger";
break;
case ConfirmDialogIcon.success:
v = "success";
break;
case ConfirmDialogIcon.warn:
v = "warn";
break;
case ConfirmDialogIcon.none:
v = "";
break;
}
return v;
}
}
Future showCustomConfirmDialog(BuildContext context, String name,
{String btnName = "确定",
ConfirmDialogIcon icon = ConfirmDialogIcon.warn}) async {
ThemeController themeController = Get.find();
return showDialog(
context: context,
barrierDismissible: true,
builder: (BuildContext context) {
return Dialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
child: Container(
width: 660.rpx,
padding: EdgeInsets.fromLTRB(16, 0, 16, 16),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
alignment: Alignment.centerRight,
child: closeIcon,
),
SizedBox(height: 60.rpx),
if ("${icon.uname}".isNotEmpty)
Center(
child: Container(
margin: EdgeInsets.only(bottom: 39.rpx),
width: 50.rpx,
height: 50.rpx,
child: Image.asset("assets/images/toast/${icon.uname}.png"),
),
),
Center(
child: Text(
'${name}',
style: TextStyle(fontSize: 16),
),
),
SizedBox(height: 20.rpx),
Container(
margin: EdgeInsets.only(top: 50.rpx, bottom: 40.rpx),
alignment: Alignment.center,
child: InkWell(
onTap: () {
Get.back(result: "confirm");
},
child: Container(
width: 260.rpx,
height: 60.rpx,
alignment: Alignment.center,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(6),
color: stringToColor("#D3B684")),
child: Text(
'$btnName',
style: TextStyle(
color: themeController.currentColor.sc3,
fontSize: 30.rpx),
),
),
),
)
],
),
),
);
},
);
}
Future showCustomConfirmAndCancelDialog(BuildContext context, String name,
{String confirmName = "确定",
String cancelName = "取消",
ConfirmDialogIcon icon = ConfirmDialogIcon.warn}) async {
ThemeController themeController = Get.find();
return showDialog(
context: context,
barrierDismissible: true,
builder: (BuildContext context) {
return Dialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
child: Container(
width: 660.rpx,
padding: EdgeInsets.fromLTRB(16, 0, 16, 16),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
alignment: Alignment.centerRight,
child: closeIcon,
),
SizedBox(height: 40.rpx),
if ("${icon.uname}".isNotEmpty)
Center(
child: Container(
margin: EdgeInsets.only(bottom: 39.rpx),
width: 50.rpx,
height: 50.rpx,
child: Image.asset("assets/images/toast/${icon.uname}.png"),
),
),
Center(
child: Text(
'${name}',
style: TextStyle(fontSize: 16),
),
),
SizedBox(height: 20.rpx),
Container(
margin: EdgeInsets.only(top: 50.rpx, bottom: 40.rpx),
alignment: Alignment.center,
child: InkWell(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
InkWell(
onTap: () {
Get.back(result: "cancel");
},
child: Container(
width: 200.rpx,
height: 60.rpx,
alignment: Alignment.center,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(6),
border: Border.all(color: Colors.black12)),
child: Text(
'$cancelName',
style:
TextStyle(color: Colors.black, fontSize: 30.rpx),
),
),
),
SizedBox(
width: 80.rpx,
),
InkWell(
onTap: () {
Get.back(result: "confirm");
},
child: Container(
width: 200.rpx,
height: 60.rpx,
alignment: Alignment.center,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(6),
color: stringToColor("#D3B684")),
child: Text(
'$confirmName',
style: TextStyle(
color: themeController.currentColor.sc3,
fontSize: 30.rpx),
),
),
)
],
)),
)
],
),
),
);
},
);
}
//权限说明弹窗
void showPermissionInfoDialog(BuildContext context, List data) {
ThemeController themeController = Get.find();
showDialog(
context: context,
barrierDismissible: false, // 点击对话框外部可关闭
builder: (BuildContext context) {
return Stack(
children: [
Positioned(
top: 30.rpx, // 控制弹窗距离顶部的位置
left: 0,
right: 0,
child: Material(
color: Colors.transparent,
child: Dialog(
backgroundColor: themeController.currentColor.sc3,
insetPadding: EdgeInsets.fromLTRB(0, 0, 0, 0),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
child: Container(
constraints: BoxConstraints(maxHeight: 500.rpx),
padding: EdgeInsets.all(16),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
),
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
...List.generate(data.length, (index) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"${data[index][0]}",
style: TextStyle(
fontSize: 30.rpx,
color: stringToColor("#333333"),
),
),
SizedBox(
height: 4.rpx,
),
Text(
"${data[index][1]}",
style: TextStyle(
fontSize: 26.rpx,
color: stringToColor("#A4AABC"),
),
),
if (index != data.length - 1)
SizedBox(
height: 18.rpx,
),
],
);
}),
],
),
),
),
),
),
),
],
);
},
);
}
void showProgressDialog(
BuildContext context,
ValueNotifier<double> progressNotifier,
ValueNotifier<bool> failureNotifier,
) {
ThemeController themeController = Get.find();
DeviceCalibrationController deviceCalibrationController = Get.find();
showDialog(
context: context,
barrierDismissible: false, // 点击对话框外部不可关闭
builder: (BuildContext dialogContext) {
return Stack(
children: [
Positioned(
top: MediaQuery.of(context).size.height * 0.4,
left: MediaQuery.of(context).size.width * 0.05,
right: MediaQuery.of(context).size.width * 0.05,
child: Material(
color: Colors.transparent,
child: Dialog(
backgroundColor: Colors.transparent,
insetPadding: EdgeInsets.zero,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
child: Container(
padding: EdgeInsets.all(16),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
),
child: ValueListenableBuilder<double>(
valueListenable: progressNotifier,
builder: (context, progress, _) {
return ValueListenableBuilder<bool>(
valueListenable: failureNotifier,
builder: (context, isFailure, __) {
// 关闭弹窗的逻辑
if (isFailure) {
// 延迟关闭弹窗和提示错误
Future.delayed(Duration(milliseconds: 300), () {
if (Navigator.canPop(dialogContext)) {
Navigator.of(dialogContext).pop();
}
});
} else if (progress >= 100) {
// 延迟关闭弹窗和提示成功(可选)
Future.delayed(Duration(milliseconds: 300), () {
if (Navigator.canPop(dialogContext)) {
Navigator.of(dialogContext).pop();
}
});
}
return Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text(
isFailure
? '失败'.tr
: '${(progress).toStringAsFixed(0)}%',
style: TextStyle(
fontSize: 26.rpx,
color: isFailure
? Colors.red
: themeController.currentColor.sc3,
),
),
SizedBox(height: 40.rpx),
Stack(
children: [
Container(
width: double.infinity,
height: 21.rpx,
decoration: BoxDecoration(
color: stringToColor("#D9D9D9"),
borderRadius: BorderRadius.circular(
AppConstants().button_container_radius,
),
),
),
Container(
width: progress /
100 *
MediaQuery.of(context).size.width *
0.8,
height: 21.rpx,
decoration: BoxDecoration(
gradient: LinearGradient(
colors: isFailure
? [themeController.currentColor.sc9]
: [
themeController
.currentColor.sc2,
themeController
.currentColor.sc2,
],
begin: Alignment.centerLeft,
end: Alignment.centerRight,
),
borderRadius: BorderRadius.circular(
AppConstants().button_container_radius,
),
),
),
],
),
],
);
},
);
},
),
),
),
),
),
],
);
},
);
}
void showSleepCalendarBottomSheet({
required BuildContext context,
int? timestamp,
int? type = 1, // 新增参数默认值为1
required void Function(DateTime selectedDate) onDateSelected,
}) {
showModalBottomSheet(
context: context,
isScrollControlled: false,
backgroundColor: Colors.transparent,
builder: (context) {
return Container(
decoration: BoxDecoration(
color: const Color(0xFF242835),
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20.rpx),
topRight: Radius.circular(20.rpx),
),
),
child: SleepCalendarWidget(
timestamp: timestamp,
type: type, // 传递类型给子组件
onDateSelected: onDateSelected,
// highlightColor: Colors.green,
),
);
},
);
}