5 changed files with 581 additions and 85 deletions
@ -1,3 +1,85 @@ |
|||
import 'package:flutter/widgets.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