5 changed files with 581 additions and 85 deletions
@ -1,3 +1,85 @@ |
|||||
|
import 'package:flutter/widgets.dart'; |
||||
import 'package:get/get.dart'; |
import 'package:get/get.dart'; |
||||
|
|
||||
class EqSettingsController extends GetxController {} |
import '../../../core/utils/logger.dart'; |
||||
|
import '../../../routes/app_routes.dart'; |
||||
|
import '../views/widgets/row_confirm_widget.dart'; |
||||
|
import '../views/widgets/row_input_widget.dart'; |
||||
|
|
||||
|
class EqSettingsController extends GetxController { |
||||
|
final RxList uiList = [ |
||||
|
{ |
||||
|
'title': '音效', |
||||
|
'templates': [], |
||||
|
}, |
||||
|
{ |
||||
|
'title': '按键功能', |
||||
|
'templates': [], |
||||
|
}, |
||||
|
{ |
||||
|
'title': '耳机功能', |
||||
|
'templates': [ |
||||
|
{ |
||||
|
'type': 'input', |
||||
|
'name': '修改名称', |
||||
|
'value': 'voitrans', |
||||
|
'onCallback': (String value) { |
||||
|
Logger.d('input', '修改名称:$value'); |
||||
|
}, |
||||
|
}, |
||||
|
{ |
||||
|
'type': 'input', |
||||
|
'name': '工作模式', |
||||
|
'value': '', |
||||
|
'onCallback': () {}, |
||||
|
}, |
||||
|
{ |
||||
|
'type': 'switch', |
||||
|
'name': '闪灯开关', |
||||
|
'value': false, |
||||
|
'onCallback': () {}, |
||||
|
}, |
||||
|
{ |
||||
|
'type': 'switch', |
||||
|
'name': '查找设备', |
||||
|
'value': false, |
||||
|
'description': '在设备上播放声音', |
||||
|
'onCallback': () {}, |
||||
|
}, |
||||
|
], |
||||
|
}, |
||||
|
{ |
||||
|
'templates': [ |
||||
|
{ |
||||
|
'type': 'confirm', |
||||
|
'name': '升级耳机固件', |
||||
|
'onCallback': () => Get.toNamed(Routes.OTA_UPGRADE), |
||||
|
}, |
||||
|
{ |
||||
|
'type': 'confirm', |
||||
|
'name': '恢复出厂设置', |
||||
|
'tips': '确定要恢复出厂设置吗?', |
||||
|
'onCallback': () { |
||||
|
Logger.d('confirm', '恢复出厂设置'); |
||||
|
}, |
||||
|
}, |
||||
|
{ |
||||
|
'type': 'confirm', |
||||
|
'name': '清除配对记录', |
||||
|
'tips': '确定要清除配对记录吗?', |
||||
|
'onCallback': () { |
||||
|
Logger.d('confirm', '清除配对记录'); |
||||
|
}, |
||||
|
}, |
||||
|
], |
||||
|
} |
||||
|
].obs; |
||||
|
|
||||
|
Widget getTemplate(Map data) { |
||||
|
return switch (data['type']) { |
||||
|
'input' => RowInputWidget(data), |
||||
|
'confirm' => RowConfirmWidget(data), |
||||
|
_ => const SizedBox.shrink(), |
||||
|
}; |
||||
|
} |
||||
|
} |
||||
|
|||||
@ -0,0 +1,96 @@ |
|||||
|
import 'package:flutter/material.dart'; |
||||
|
import 'package:flutter_screenutil/flutter_screenutil.dart'; |
||||
|
import 'package:get/get.dart'; |
||||
|
|
||||
|
class RowConfirmWidget extends StatefulWidget { |
||||
|
final Map templateData; |
||||
|
|
||||
|
const RowConfirmWidget(this.templateData, {super.key}); |
||||
|
|
||||
|
@override |
||||
|
State<RowConfirmWidget> createState() => _RowConfirmWidgetState(); |
||||
|
} |
||||
|
|
||||
|
class _RowConfirmWidgetState extends State<RowConfirmWidget> { |
||||
|
Map get _templateData => widget.templateData; |
||||
|
|
||||
|
@override |
||||
|
Widget build(BuildContext context) { |
||||
|
final isDarkMode = Theme.of(context).brightness == Brightness.dark; |
||||
|
|
||||
|
return GestureDetector( |
||||
|
onTap: () { |
||||
|
if (_templateData['tips'] != null) { |
||||
|
_alertDialog(isDarkMode); |
||||
|
} else { |
||||
|
_templateData['onCallback'](); |
||||
|
} |
||||
|
}, |
||||
|
behavior: HitTestBehavior.translucent, |
||||
|
child: Padding( |
||||
|
padding: EdgeInsets.fromLTRB(10.w, 10.w, 0, 10.w), |
||||
|
child: Row( |
||||
|
children: [ |
||||
|
Expanded( |
||||
|
child: Text( |
||||
|
_templateData['name'], |
||||
|
style: TextStyle( |
||||
|
fontSize: 14.sp, |
||||
|
color: isDarkMode ? Colors.white : Colors.black, |
||||
|
), |
||||
|
), |
||||
|
), |
||||
|
Icon( |
||||
|
Icons.chevron_right, |
||||
|
size: 26.w, |
||||
|
color: Colors.blue, |
||||
|
), |
||||
|
], |
||||
|
), |
||||
|
), |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
void _alertDialog(bool isDarkMode) { |
||||
|
Get.dialog( |
||||
|
AlertDialog( |
||||
|
backgroundColor: isDarkMode ? Colors.grey[900] : Colors.white, |
||||
|
title: Text( |
||||
|
_templateData['name'], |
||||
|
style: TextStyle( |
||||
|
color: isDarkMode ? Colors.white : Colors.black87, |
||||
|
), |
||||
|
), |
||||
|
content: Text( |
||||
|
_templateData['tips'], |
||||
|
style: TextStyle( |
||||
|
color: isDarkMode ? Colors.white70 : Colors.black54, |
||||
|
), |
||||
|
), |
||||
|
actions: [ |
||||
|
TextButton( |
||||
|
onPressed: () => Get.back(), |
||||
|
child: Text( |
||||
|
'cancel'.tr, // 取消 |
||||
|
style: TextStyle( |
||||
|
color: isDarkMode ? Colors.white70 : Colors.black54, |
||||
|
), |
||||
|
), |
||||
|
), |
||||
|
TextButton( |
||||
|
onPressed: () { |
||||
|
_templateData['onCallback'](); |
||||
|
Get.back(); |
||||
|
}, |
||||
|
child: Text( |
||||
|
'confirm'.tr, // 确定 |
||||
|
style: TextStyle( |
||||
|
color: isDarkMode ? Colors.red[300] : Colors.red[600], |
||||
|
), |
||||
|
), |
||||
|
), |
||||
|
], |
||||
|
), |
||||
|
); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,231 @@ |
|||||
|
import 'package:flutter/material.dart'; |
||||
|
import 'package:flutter_screenutil/flutter_screenutil.dart'; |
||||
|
import 'package:get/get.dart'; |
||||
|
|
||||
|
class RowInputWidget extends StatefulWidget { |
||||
|
final Map templateData; |
||||
|
|
||||
|
const RowInputWidget(this.templateData, {super.key}); |
||||
|
|
||||
|
@override |
||||
|
State<RowInputWidget> createState() => _RowInputWidgetState(); |
||||
|
} |
||||
|
|
||||
|
class _RowInputWidgetState extends State<RowInputWidget> { |
||||
|
Map get _templateData => widget.templateData; |
||||
|
|
||||
|
@override |
||||
|
Widget build(BuildContext context) { |
||||
|
final isDarkMode = Theme.of(context).brightness == Brightness.dark; |
||||
|
|
||||
|
return GestureDetector( |
||||
|
onTap: () => _inputBottomSheet(isDarkMode), |
||||
|
behavior: HitTestBehavior.translucent, |
||||
|
child: Padding( |
||||
|
padding: EdgeInsets.fromLTRB(10.w, 10.w, 0, 10.w), |
||||
|
child: Row( |
||||
|
children: [ |
||||
|
Expanded( |
||||
|
child: Text( |
||||
|
_templateData['name'], |
||||
|
style: TextStyle( |
||||
|
fontSize: 14.sp, |
||||
|
color: isDarkMode ? Colors.white : Colors.black, |
||||
|
), |
||||
|
), |
||||
|
), |
||||
|
Text( |
||||
|
_templateData['value'], |
||||
|
style: TextStyle( |
||||
|
fontSize: 12.sp, |
||||
|
color: isDarkMode ? Colors.white : Colors.grey, |
||||
|
), |
||||
|
), |
||||
|
Icon( |
||||
|
Icons.chevron_right, |
||||
|
size: 26.w, |
||||
|
color: Colors.blue, |
||||
|
), |
||||
|
], |
||||
|
), |
||||
|
), |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
void _inputBottomSheet(bool isDarkMode) { |
||||
|
Get.bottomSheet( |
||||
|
InputBox(_templateData['name'], _templateData['value']), |
||||
|
isScrollControlled: true, |
||||
|
backgroundColor: isDarkMode ? Colors.grey[800] : Colors.grey[100], |
||||
|
shape: RoundedRectangleBorder( |
||||
|
borderRadius: BorderRadius.vertical( |
||||
|
top: Radius.circular(12.r), |
||||
|
), |
||||
|
), |
||||
|
).then((value) { |
||||
|
if (value != null) { |
||||
|
setState(() { |
||||
|
_templateData['value'] = value; |
||||
|
}); |
||||
|
_templateData['onCallback'](value); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
class InputBox extends StatefulWidget { |
||||
|
final String title; |
||||
|
final String inputText; |
||||
|
|
||||
|
const InputBox(this.title, this.inputText, {super.key}); |
||||
|
|
||||
|
@override |
||||
|
State<InputBox> createState() => _InputBoxState(); |
||||
|
} |
||||
|
|
||||
|
class _InputBoxState extends State<InputBox> { |
||||
|
final TextEditingController _inputController = TextEditingController(); |
||||
|
|
||||
|
@override |
||||
|
void initState() { |
||||
|
super.initState(); |
||||
|
_inputController.text = widget.inputText; |
||||
|
} |
||||
|
|
||||
|
@override |
||||
|
void dispose() { |
||||
|
_inputController.dispose(); |
||||
|
super.dispose(); |
||||
|
} |
||||
|
|
||||
|
@override |
||||
|
Widget build(BuildContext context) { |
||||
|
return Padding( |
||||
|
padding: EdgeInsets.symmetric(horizontal: 12.w), |
||||
|
child: Column( |
||||
|
mainAxisSize: MainAxisSize.min, |
||||
|
children: [ |
||||
|
Container( |
||||
|
padding: EdgeInsets.symmetric(vertical: 10.w), |
||||
|
child: Row( |
||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween, |
||||
|
children: [ |
||||
|
Text( |
||||
|
widget.title, |
||||
|
style: TextStyle( |
||||
|
fontSize: 16.sp, |
||||
|
color: Colors.black87, |
||||
|
fontWeight: FontWeight.bold, |
||||
|
), |
||||
|
), |
||||
|
GestureDetector( |
||||
|
onTap: () => Get.back(), |
||||
|
child: Container( |
||||
|
width: 26.w, |
||||
|
height: 26.w, |
||||
|
decoration: BoxDecoration( |
||||
|
color: Colors.white, |
||||
|
borderRadius: BorderRadius.circular(26.r), |
||||
|
), |
||||
|
child: Icon( |
||||
|
Icons.close, |
||||
|
size: 18.w, |
||||
|
color: Colors.grey[400], |
||||
|
), |
||||
|
), |
||||
|
) |
||||
|
], |
||||
|
), |
||||
|
), |
||||
|
Divider( |
||||
|
height: 1, |
||||
|
color: Colors.grey[300], |
||||
|
), |
||||
|
Container( |
||||
|
margin: EdgeInsets.symmetric(vertical: 20.w), |
||||
|
alignment: Alignment.center, |
||||
|
decoration: BoxDecoration( |
||||
|
color: Colors.white, |
||||
|
borderRadius: BorderRadius.circular(12.w), |
||||
|
boxShadow: [ |
||||
|
BoxShadow( |
||||
|
color: Colors.black.withValues(alpha: 0.05), |
||||
|
blurRadius: 10, |
||||
|
offset: const Offset(0, 2), |
||||
|
), |
||||
|
], |
||||
|
), |
||||
|
child: TextField( |
||||
|
controller: _inputController, |
||||
|
style: TextStyle( |
||||
|
color: Colors.black87, |
||||
|
fontSize: 16.sp, |
||||
|
), |
||||
|
decoration: InputDecoration( |
||||
|
hintText: 'maxCharacters'.tr, |
||||
|
hintStyle: TextStyle( |
||||
|
color: Colors.black54, |
||||
|
fontSize: 16.sp, |
||||
|
), |
||||
|
isDense: true, |
||||
|
fillColor: Colors.transparent, |
||||
|
border: InputBorder.none, |
||||
|
contentPadding: EdgeInsets.all(10.w), |
||||
|
), |
||||
|
), |
||||
|
), |
||||
|
Padding( |
||||
|
padding: EdgeInsets.only(bottom: 20.w), |
||||
|
child: Row( |
||||
|
children: [ |
||||
|
Expanded( |
||||
|
child: GestureDetector( |
||||
|
onTap: () => Get.back(), |
||||
|
child: Container( |
||||
|
height: 48.w, |
||||
|
alignment: Alignment.center, |
||||
|
decoration: BoxDecoration( |
||||
|
color: Colors.grey[300], |
||||
|
borderRadius: BorderRadius.circular(12.r), |
||||
|
), |
||||
|
child: Text( |
||||
|
'cancel'.tr, // 取消 |
||||
|
style: TextStyle( |
||||
|
fontSize: 16.sp, |
||||
|
color: Colors.black, |
||||
|
), |
||||
|
), |
||||
|
), |
||||
|
), |
||||
|
), |
||||
|
10.horizontalSpace, |
||||
|
Expanded( |
||||
|
child: GestureDetector( |
||||
|
onTap: () { |
||||
|
Get.back(result: _inputController.text); |
||||
|
}, |
||||
|
child: Container( |
||||
|
height: 48.w, |
||||
|
alignment: Alignment.center, |
||||
|
decoration: BoxDecoration( |
||||
|
color: Colors.black, |
||||
|
borderRadius: BorderRadius.circular(12.r), |
||||
|
), |
||||
|
child: Text( |
||||
|
'confirm'.tr, // 确认 |
||||
|
style: TextStyle( |
||||
|
fontSize: 16.sp, |
||||
|
color: Colors.white, |
||||
|
), |
||||
|
), |
||||
|
), |
||||
|
), |
||||
|
), |
||||
|
], |
||||
|
), |
||||
|
), |
||||
|
], |
||||
|
), |
||||
|
); |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue