1.UI 优化
2.新增打包构建脚本
This commit is contained in:
BIN
assets/images/image_copy.png
Normal file
BIN
assets/images/image_copy.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 795 B |
BIN
assets/images/image_delete.png
Normal file
BIN
assets/images/image_delete.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1011 B |
Binary file not shown.
|
Before Width: | Height: | Size: 8.9 KiB After Width: | Height: | Size: 4.6 KiB |
BIN
assets/images/image_vs.png
Normal file
BIN
assets/images/image_vs.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.5 KiB |
1
build-apk-split.sh
Normal file
1
build-apk-split.sh
Normal file
@@ -0,0 +1 @@
|
||||
flutter build apk --release --split-per-abi
|
||||
1
build-apk.sh
Normal file
1
build-apk.sh
Normal file
@@ -0,0 +1 @@
|
||||
flutter build apk --release
|
||||
@@ -29,7 +29,7 @@ class RecordHeaderWidget extends StatelessWidget {
|
||||
|
||||
void _mockCopyEventInfo() {
|
||||
const strTemp =
|
||||
'{"title":"郑昌梦 丨黄伟依 空中格斗赛 小学组","address":"广东省汕头市番禺区青蓝街 111 号","filename":"郑昌梦_黄伟依_6月3日测试-1_空中格斗赛"}';
|
||||
'{"title":"蔡依婷vs夏志豪 空中格斗赛 初中组","address":"黑龙江省鹤岗市11111","filename":"蔡依婷_夏志豪_测试循环赛-7_空中格斗赛"}';
|
||||
Clipboard.setData(const ClipboardData(text: strTemp));
|
||||
AppToast.show('模拟复制赛事信息成功');
|
||||
}
|
||||
@@ -47,7 +47,7 @@ class RecordHeaderWidget extends StatelessWidget {
|
||||
children: [
|
||||
Image.asset(
|
||||
Assets.images.imageLogo.path,
|
||||
width: 84.r,
|
||||
width: 24.r,
|
||||
height: 24.r,
|
||||
fit: BoxFit.contain,
|
||||
),
|
||||
@@ -92,7 +92,7 @@ class _HeaderEventTitleRow extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
@@ -101,7 +101,7 @@ class _HeaderEventTitleRow extends StatelessWidget {
|
||||
fontSize: 12.sp,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
textAlign: TextAlign.right,
|
||||
textAlign: TextAlign.center,
|
||||
maxLines: 3,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
@@ -109,7 +109,12 @@ class _HeaderEventTitleRow extends StatelessWidget {
|
||||
if (!isRecording)
|
||||
IconButton(
|
||||
onPressed: onClearEventInfo,
|
||||
icon: Icon(Icons.delete_outline, color: Colors.white, size: 22.r),
|
||||
icon: Assets.images.imageDelete.image(
|
||||
width: 15.r,
|
||||
height: 15.r,
|
||||
fit: BoxFit.contain,
|
||||
excludeFromSemantics: true,
|
||||
),
|
||||
padding: EdgeInsets.zero,
|
||||
constraints: BoxConstraints(minWidth: 40.r, minHeight: 40.r),
|
||||
tooltip: '删除',
|
||||
@@ -137,6 +142,12 @@ class _HeaderPasteActions extends StatelessWidget {
|
||||
_HeaderActionButton(
|
||||
label: '粘贴选手信息',
|
||||
onPressed: () => onPasteEventInfo(),
|
||||
icon: Assets.images.imageCopy.image(
|
||||
width: 10.r,
|
||||
height: 10.r,
|
||||
fit: BoxFit.contain,
|
||||
excludeFromSemantics: true,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
@@ -144,23 +155,32 @@ class _HeaderPasteActions extends StatelessWidget {
|
||||
}
|
||||
|
||||
class _HeaderActionButton extends StatelessWidget {
|
||||
const _HeaderActionButton({required this.label, required this.onPressed});
|
||||
const _HeaderActionButton({
|
||||
required this.label,
|
||||
required this.onPressed,
|
||||
this.icon,
|
||||
});
|
||||
|
||||
final String label;
|
||||
final VoidCallback onPressed;
|
||||
final Widget? icon;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return TextButton.icon(
|
||||
onPressed: onPressed,
|
||||
icon: Icon(Icons.content_paste, size: 18.r),
|
||||
icon: icon ?? Icon(Icons.content_paste, size: 10.r),
|
||||
label: Text(label),
|
||||
|
||||
style: TextButton.styleFrom(
|
||||
minimumSize: Size.zero, // 取消 40dp 最小高度
|
||||
tapTargetSize: MaterialTapTargetSize.shrinkWrap, // 取消额外点击热区
|
||||
foregroundColor: Colors.white,
|
||||
backgroundColor: Colors.black.withValues(alpha: 0.5),
|
||||
padding: EdgeInsets.symmetric(horizontal: 14.r, vertical: 8.r),
|
||||
textStyle: TextStyle(fontSize: 10.sp),
|
||||
padding: EdgeInsets.symmetric(horizontal: 7.r, vertical: 4.r),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(20.r),
|
||||
borderRadius: BorderRadius.circular(25.r),
|
||||
side: const BorderSide(color: Colors.white30),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -33,7 +33,7 @@ class _RecordTimerWidgetState extends ConsumerState<RecordTimerWidget> {
|
||||
child: Text(
|
||||
displayTime,
|
||||
style: TextStyle(
|
||||
color: isRecording ? Colors.white : Colors.white70,
|
||||
color: Colors.white,
|
||||
fontSize: 20.sp,
|
||||
shadows: [Shadow(color: Colors.black54, blurRadius: 6.r)],
|
||||
),
|
||||
|
||||
@@ -14,6 +14,14 @@ import 'package:flutter/widgets.dart';
|
||||
class $AssetsImagesGen {
|
||||
const $AssetsImagesGen();
|
||||
|
||||
/// File path: assets/images/image_copy.png
|
||||
AssetGenImage get imageCopy =>
|
||||
const AssetGenImage('assets/images/image_copy.png');
|
||||
|
||||
/// File path: assets/images/image_delete.png
|
||||
AssetGenImage get imageDelete =>
|
||||
const AssetGenImage('assets/images/image_delete.png');
|
||||
|
||||
/// File path: assets/images/image_dialog_bg.png
|
||||
AssetGenImage get imageDialogBg =>
|
||||
const AssetGenImage('assets/images/image_dialog_bg.png');
|
||||
@@ -23,7 +31,12 @@ class $AssetsImagesGen {
|
||||
const AssetGenImage('assets/images/image_logo.png');
|
||||
|
||||
/// List of all assets
|
||||
List<AssetGenImage> get values => [imageDialogBg, imageLogo];
|
||||
List<AssetGenImage> get values => [
|
||||
imageCopy,
|
||||
imageDelete,
|
||||
imageDialogBg,
|
||||
imageLogo,
|
||||
];
|
||||
}
|
||||
|
||||
class Assets {
|
||||
|
||||
53
test/features/recording/widget_record_header_test.dart
Normal file
53
test/features/recording/widget_record_header_test.dart
Normal file
@@ -0,0 +1,53 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:recording_tool/features/recording/widgets/widget_record_header.dart';
|
||||
import 'package:recording_tool/gen/assets.gen.dart';
|
||||
|
||||
void main() {
|
||||
Future<void> pumpHeader(
|
||||
WidgetTester tester, {
|
||||
required bool hasValidClipboardInfo,
|
||||
String? eventTitle,
|
||||
}) async {
|
||||
await tester.pumpWidget(
|
||||
ScreenUtilInit(
|
||||
designSize: const Size(375, 812),
|
||||
builder: (context, _) {
|
||||
return MaterialApp(
|
||||
home: Scaffold(
|
||||
body: RecordHeaderWidget(
|
||||
hasValidClipboardInfo: hasValidClipboardInfo,
|
||||
eventTitle: eventTitle,
|
||||
isRecording: false,
|
||||
elapsedLabel: '00:00',
|
||||
onPasteEventInfo: () async {},
|
||||
onClearEventInfo: () {},
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
testWidgets('paste player info button uses copy image asset', (tester) async {
|
||||
await pumpHeader(tester, hasValidClipboardInfo: false);
|
||||
|
||||
expect(find.text('粘贴选手信息'), findsOneWidget);
|
||||
expect(find.image(AssetImage(Assets.images.imageCopy.path)), findsOne);
|
||||
});
|
||||
|
||||
testWidgets('clear player info button uses delete image asset', (
|
||||
tester,
|
||||
) async {
|
||||
await pumpHeader(
|
||||
tester,
|
||||
hasValidClipboardInfo: true,
|
||||
eventTitle: '王东方 丨李想 空中格斗赛',
|
||||
);
|
||||
|
||||
expect(find.text('王东方 丨李想 空中格斗赛'), findsOneWidget);
|
||||
expect(find.image(AssetImage(Assets.images.imageDelete.path)), findsOne);
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user