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