Files
tuiche/lib/pages/common/selectDialog.dart
2025-05-13 11:59:04 +08:00

915 lines
36 KiB
Dart

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/tool/TopSlideNotification.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();
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();
}
TopSlideNotification.show(
context,
text: "设备校准失败".tr,
textColor: Colors.red,
);
});
} else if (progress >= 1.0) {
// 延迟关闭弹窗和提示成功(可选)
Future.delayed(Duration(milliseconds: 300), () {
if (Navigator.canPop(dialogContext)) {
Navigator.of(dialogContext).pop();
}
TopSlideNotification.show(
context,
text: "设备校准完成".tr,
textColor: themeController.currentColor.sc3,
);
});
}
return Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text(
isFailure
? '失败'.tr
: '${(progress * 100).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 *
MediaQuery.of(context).size.width *
0.8,
height: 10.rpx,
decoration: BoxDecoration(
gradient: LinearGradient(
colors: isFailure
? [themeController.currentColor.sc9]
: [
themeController
.currentColor.sc1,
themeController
.currentColor.sc2,
],
begin: Alignment.centerLeft,
end: Alignment.centerRight,
),
borderRadius:
BorderRadius.circular(5.rpx),
),
),
],
),
],
);
},
);
},
),
),
),
),
),
],
);
},
);
}