优化人工处理弹窗 UI
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:recording_tool/features/competition_teams/model/model_competition_team_detail.dart';
|
||||
import 'package:recording_tool/shared/widgets/app_button.dart';
|
||||
import 'package:recording_tool/gen/assets.gen.dart';
|
||||
|
||||
/// 弹窗回传选中侧索引:0 = teamA(红队),1 = teamB(蓝队)
|
||||
class ManualWinnerDialog extends StatefulWidget {
|
||||
@@ -62,35 +62,41 @@ class _ManualWinnerDialogState extends State<ManualWinnerDialog> {
|
||||
Widget build(BuildContext context) {
|
||||
final teamA = _teamA;
|
||||
final teamB = _teamB;
|
||||
final maxHeight = MediaQuery.sizeOf(context).height * 0.78;
|
||||
|
||||
return AlertDialog(
|
||||
insetPadding: EdgeInsets.symmetric(horizontal: 22.w),
|
||||
contentPadding: EdgeInsets.zero,
|
||||
clipBehavior: Clip.antiAlias,
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(18.r)),
|
||||
content: SizedBox(
|
||||
width: 320.w,
|
||||
return Dialog(
|
||||
insetPadding: EdgeInsets.symmetric(horizontal: 48.w),
|
||||
backgroundColor: Colors.transparent,
|
||||
elevation: 0,
|
||||
child: ConstrainedBox(
|
||||
constraints: BoxConstraints(maxWidth: 380.w, maxHeight: maxHeight),
|
||||
child: Stack(
|
||||
clipBehavior: Clip.none,
|
||||
children: [
|
||||
ClipRRect(
|
||||
borderRadius: BorderRadius.circular(16.r),
|
||||
child: Material(
|
||||
color: Colors.white,
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Image.asset(
|
||||
'assets/images/image_dialog_bg.png',
|
||||
width: 320.w,
|
||||
height: 112.h,
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.fromLTRB(20.w, 8.h, 20.w, 20.h),
|
||||
padding: EdgeInsets.fromLTRB(18.w, 18.h, 18.w, 18.h),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
SizedBox(height: 26.h),
|
||||
Text(
|
||||
'请在比赛结束前处理',
|
||||
key: const ValueKey('manual-winner-dialog-title'),
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 20.sp,
|
||||
fontSize: 18.sp,
|
||||
height: 1.3,
|
||||
fontWeight: FontWeight.w700,
|
||||
color: const Color(0xFF20242B),
|
||||
fontFamily: 'PingFang SC',
|
||||
),
|
||||
),
|
||||
SizedBox(height: 16.h),
|
||||
@@ -98,9 +104,10 @@ class _ManualWinnerDialogState extends State<ManualWinnerDialog> {
|
||||
_TeamChoice(
|
||||
team: teamA,
|
||||
sideIndex: 0,
|
||||
color: const Color(0xFFFF6B75),
|
||||
color: const Color(0xFFFF6575),
|
||||
selected: _selectedSideIndex == 0,
|
||||
onTap: () => setState(() => _selectedSideIndex = 0),
|
||||
onTap: () =>
|
||||
setState(() => _selectedSideIndex = 0),
|
||||
),
|
||||
SizedBox(height: 10.h),
|
||||
],
|
||||
@@ -108,24 +115,26 @@ class _ManualWinnerDialogState extends State<ManualWinnerDialog> {
|
||||
_TeamChoice(
|
||||
team: teamB,
|
||||
sideIndex: 1,
|
||||
color: const Color(0xFF20BFA9),
|
||||
color: const Color(0xFF21C5AC),
|
||||
selected: _selectedSideIndex == 1,
|
||||
onTap: () => setState(() => _selectedSideIndex = 1),
|
||||
onTap: () =>
|
||||
setState(() => _selectedSideIndex = 1),
|
||||
),
|
||||
SizedBox(height: 20.h),
|
||||
SizedBox(height: 18.h),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: AppButton(
|
||||
child: _DialogActionButton(
|
||||
label: '取消',
|
||||
variant: AppButtonVariant.secondary,
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
onPressed: () =>
|
||||
Navigator.of(context).pop(),
|
||||
),
|
||||
),
|
||||
SizedBox(width: 14.w),
|
||||
Expanded(
|
||||
child: AppButton(
|
||||
child: _DialogActionButton(
|
||||
label: '确定',
|
||||
filled: true,
|
||||
onPressed: _selectedSideIndex == null
|
||||
? null
|
||||
: () => Navigator.of(
|
||||
@@ -142,6 +151,22 @@ class _ManualWinnerDialogState extends State<ManualWinnerDialog> {
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
top: -90.h,
|
||||
left: 0,
|
||||
right: 0,
|
||||
child: Image.asset(
|
||||
Assets.images.imageDialogBg.path,
|
||||
width: double.infinity,
|
||||
height: 112.h,
|
||||
fit: BoxFit.cover,
|
||||
alignment: Alignment.topCenter,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -167,12 +192,15 @@ class _TeamChoice extends StatelessWidget {
|
||||
? team.teamName!
|
||||
: '未命名队伍';
|
||||
final players = team.playerNames;
|
||||
final backgroundColor = selected
|
||||
? color.withValues(alpha: 0.13)
|
||||
: color.withValues(alpha: 0.07);
|
||||
return Semantics(
|
||||
selected: selected,
|
||||
button: true,
|
||||
label: '选择$name直接获胜',
|
||||
child: Material(
|
||||
color: color.withValues(alpha: selected ? 0.16 : 0.08),
|
||||
color: backgroundColor,
|
||||
borderRadius: BorderRadius.circular(12.r),
|
||||
child: InkWell(
|
||||
key: ValueKey('winner-choice-side-$sideIndex'),
|
||||
@@ -180,12 +208,12 @@ class _TeamChoice extends StatelessWidget {
|
||||
borderRadius: BorderRadius.circular(12.r),
|
||||
child: Container(
|
||||
width: double.infinity,
|
||||
padding: EdgeInsets.symmetric(horizontal: 14.w, vertical: 12.h),
|
||||
padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 12.h),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(12.r),
|
||||
border: Border.all(
|
||||
color: selected ? color : color.withValues(alpha: 0.35),
|
||||
width: selected ? 2 : 1,
|
||||
color: selected ? color : color.withValues(alpha: 0.32),
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
child: Row(
|
||||
@@ -196,11 +224,23 @@ class _TeamChoice extends StatelessWidget {
|
||||
height: 22.r,
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
border: Border.all(color: selected ? color : Colors.grey),
|
||||
color: selected ? color : Colors.transparent,
|
||||
border: Border.all(
|
||||
color: selected ? color : const Color(0xFFB0B4BB),
|
||||
width: 1.2.r,
|
||||
),
|
||||
color: Colors.transparent,
|
||||
),
|
||||
child: selected
|
||||
? Icon(Icons.check, size: 15.r, color: Colors.white)
|
||||
? Center(
|
||||
child: Container(
|
||||
width: 10.r,
|
||||
height: 10.r,
|
||||
decoration: BoxDecoration(
|
||||
color: color,
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
),
|
||||
)
|
||||
: null,
|
||||
),
|
||||
SizedBox(width: 12.w),
|
||||
@@ -210,19 +250,27 @@ class _TeamChoice extends StatelessWidget {
|
||||
children: [
|
||||
Text(
|
||||
name,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
fontSize: 17.sp,
|
||||
fontWeight: FontWeight.w600,
|
||||
height: 1.25,
|
||||
fontWeight: FontWeight.w700,
|
||||
color: const Color(0xFF20242B),
|
||||
fontFamily: 'PingFang SC',
|
||||
),
|
||||
),
|
||||
if (players.isNotEmpty) ...[
|
||||
SizedBox(height: 4.h),
|
||||
Text(
|
||||
players,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
fontSize: 14.sp,
|
||||
color: const Color(0xFF606874),
|
||||
fontSize: 15.sp,
|
||||
height: 1.25,
|
||||
color: const Color(0xFF69717E),
|
||||
fontFamily: 'PingFang SC',
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -232,10 +280,12 @@ class _TeamChoice extends StatelessWidget {
|
||||
SizedBox(width: 8.w),
|
||||
Text(
|
||||
'直接获胜',
|
||||
maxLines: 1,
|
||||
style: TextStyle(
|
||||
fontSize: 13.sp,
|
||||
fontWeight: FontWeight.w600,
|
||||
fontSize: 15.sp,
|
||||
fontWeight: FontWeight.w700,
|
||||
color: color,
|
||||
fontFamily: 'PingFang SC',
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -246,3 +296,58 @@ class _TeamChoice extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _DialogActionButton extends StatelessWidget {
|
||||
const _DialogActionButton({
|
||||
required this.label,
|
||||
required this.onPressed,
|
||||
this.filled = false,
|
||||
});
|
||||
|
||||
final String label;
|
||||
final VoidCallback? onPressed;
|
||||
final bool filled;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final enabled = onPressed != null;
|
||||
final radius = BorderRadius.circular(24.r);
|
||||
final backgroundColor = filled
|
||||
? (enabled ? null : const Color(0xFFD2D3D8))
|
||||
: const Color(0xFFF1F1F1);
|
||||
final gradient = filled && enabled
|
||||
? const LinearGradient(colors: [Color(0xFF2F8DFF), Color(0xFF58D1EE)])
|
||||
: null;
|
||||
|
||||
return SizedBox(
|
||||
height: 40.h,
|
||||
child: DecoratedBox(
|
||||
decoration: BoxDecoration(
|
||||
color: backgroundColor,
|
||||
gradient: gradient,
|
||||
borderRadius: radius,
|
||||
),
|
||||
child: Material(
|
||||
color: Colors.transparent,
|
||||
child: InkWell(
|
||||
onTap: onPressed,
|
||||
borderRadius: radius,
|
||||
child: Center(
|
||||
child: Text(
|
||||
label,
|
||||
style: TextStyle(
|
||||
fontSize: 15.sp,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: filled
|
||||
? (enabled ? Colors.white : const Color(0xFF8D9098))
|
||||
: const Color(0xFF343941),
|
||||
fontFamily: 'PingFang SC',
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user