2 changed files with 198 additions and 3 deletions
@ -0,0 +1,187 @@ |
|||||
|
import 'package:flutter/material.dart'; |
||||
|
import 'package:flutter_screenutil/flutter_screenutil.dart'; |
||||
|
import 'package:get/get.dart'; |
||||
|
|
||||
|
class RowRadioWidget extends StatefulWidget { |
||||
|
final Map templateData; |
||||
|
|
||||
|
const RowRadioWidget(this.templateData, {super.key}); |
||||
|
|
||||
|
@override |
||||
|
State<RowRadioWidget> createState() => _RowRadioWidgetState(); |
||||
|
} |
||||
|
|
||||
|
class _RowRadioWidgetState extends State<RowRadioWidget> { |
||||
|
Map get _templateData => widget.templateData; |
||||
|
|
||||
|
String _label = ''; |
||||
|
|
||||
|
@override |
||||
|
void initState() { |
||||
|
super.initState(); |
||||
|
_label = _templateData['options'].firstWhere( |
||||
|
(option) => option['value'] == _templateData['value'], |
||||
|
orElse: () => {'label': ''}, |
||||
|
)['label']; |
||||
|
} |
||||
|
|
||||
|
@override |
||||
|
Widget build(BuildContext context) { |
||||
|
final isDarkMode = Theme.of(context).brightness == Brightness.dark; |
||||
|
|
||||
|
return GestureDetector( |
||||
|
onTap: () => _radioDialog(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( |
||||
|
_label, |
||||
|
style: TextStyle( |
||||
|
fontSize: 12.sp, |
||||
|
color: isDarkMode ? Colors.white : Colors.grey, |
||||
|
), |
||||
|
), |
||||
|
Icon( |
||||
|
Icons.chevron_right, |
||||
|
size: 26.w, |
||||
|
color: Colors.blue, |
||||
|
), |
||||
|
], |
||||
|
), |
||||
|
), |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
void _radioDialog(bool isDarkMode) { |
||||
|
Get.dialog( |
||||
|
Dialog( |
||||
|
backgroundColor: isDarkMode ? Colors.grey[900] : Colors.white, |
||||
|
shape: RoundedRectangleBorder( |
||||
|
borderRadius: BorderRadius.circular(16.r), |
||||
|
), |
||||
|
child: Padding( |
||||
|
padding: EdgeInsets.all(12.w), |
||||
|
child: Column( |
||||
|
mainAxisSize: MainAxisSize.min, |
||||
|
crossAxisAlignment: CrossAxisAlignment.start, |
||||
|
children: [ |
||||
|
Text( |
||||
|
_templateData['name'], |
||||
|
style: TextStyle( |
||||
|
fontSize: 18.sp, |
||||
|
fontWeight: FontWeight.w600, |
||||
|
color: isDarkMode ? Colors.white : Colors.black87, |
||||
|
), |
||||
|
), |
||||
|
SizedBox(height: 16.h), |
||||
|
Container( |
||||
|
constraints: BoxConstraints(maxHeight: 0.5.sh), |
||||
|
child: SingleChildScrollView( |
||||
|
child: Column( |
||||
|
mainAxisSize: MainAxisSize.min, |
||||
|
children: _templateData['options'] |
||||
|
.map<Widget>((option) => _item(isDarkMode, option)) |
||||
|
.toList(), |
||||
|
), |
||||
|
), |
||||
|
), |
||||
|
SizedBox(height: 16.h), |
||||
|
Row( |
||||
|
mainAxisAlignment: MainAxisAlignment.end, |
||||
|
children: [ |
||||
|
TextButton( |
||||
|
onPressed: () => Get.back(), |
||||
|
child: Text( |
||||
|
'cancel'.tr, // 取消 |
||||
|
style: TextStyle( |
||||
|
color: isDarkMode ? Colors.white70 : Colors.black54, |
||||
|
), |
||||
|
), |
||||
|
), |
||||
|
], |
||||
|
), |
||||
|
], |
||||
|
), |
||||
|
), |
||||
|
), |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
Widget _item(bool isDarkMode, Map option) { |
||||
|
return GestureDetector( |
||||
|
onTap: () { |
||||
|
setState(() { |
||||
|
_label = option['label']; |
||||
|
}); |
||||
|
_templateData['value'] = option['value']; |
||||
|
_templateData['onCallback'](option['value']); |
||||
|
Get.back(); |
||||
|
}, |
||||
|
child: Container( |
||||
|
margin: EdgeInsets.only(bottom: 10.h), |
||||
|
padding: EdgeInsets.all(10.w), |
||||
|
decoration: BoxDecoration( |
||||
|
color: _templateData['value'] == option['value'] |
||||
|
? (isDarkMode |
||||
|
? Colors.teal[900]!.withValues(alpha: 0.3) |
||||
|
: Colors.teal[50]!) |
||||
|
: (isDarkMode |
||||
|
? Colors.white.withValues(alpha: 0.05) |
||||
|
: Colors.grey[100]!), |
||||
|
borderRadius: BorderRadius.circular(12.r), |
||||
|
border: Border.all( |
||||
|
color: _templateData['value'] == option['value'] |
||||
|
? (isDarkMode ? Colors.teal[300]! : Colors.teal[600]!) |
||||
|
: Colors.transparent, |
||||
|
width: 1, |
||||
|
), |
||||
|
), |
||||
|
child: Row( |
||||
|
children: [ |
||||
|
Expanded( |
||||
|
child: Text( |
||||
|
option['label'], |
||||
|
style: TextStyle( |
||||
|
fontSize: 16.sp, |
||||
|
fontWeight: FontWeight.w500, |
||||
|
color: isDarkMode ? Colors.white : Colors.black87, |
||||
|
), |
||||
|
overflow: TextOverflow.ellipsis, |
||||
|
), |
||||
|
), |
||||
|
Container( |
||||
|
width: 24.w, |
||||
|
height: 24.w, |
||||
|
decoration: BoxDecoration( |
||||
|
color: _templateData['value'] == option['value'] |
||||
|
? (isDarkMode ? Colors.teal[300] : Colors.teal[600]) |
||||
|
: (isDarkMode |
||||
|
? Colors.white.withValues(alpha: 0.1) |
||||
|
: Colors.grey[300]), |
||||
|
shape: BoxShape.circle, |
||||
|
), |
||||
|
child: _templateData['value'] == option['value'] |
||||
|
? Icon( |
||||
|
Icons.check, |
||||
|
size: 16.w, |
||||
|
color: Colors.white, |
||||
|
) |
||||
|
: null, |
||||
|
), |
||||
|
], |
||||
|
), |
||||
|
), |
||||
|
); |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue