实现缩放功能:增加缩放功能检索和设置方法,更新UI以支持缩放调整,增强缩放比例的状态管理。

This commit is contained in:
2026-06-12 16:38:31 +08:00
parent cf1c2d7d0e
commit a3a02e623f
11 changed files with 573 additions and 18 deletions

View File

@@ -170,7 +170,7 @@ class _HeaderPasteActions extends StatelessWidget {
return Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
// _HeaderActionButton(label: 'mock', onPressed: onMockCopy),
_HeaderActionButton(label: 'mock', onPressed: onMockCopy),
_HeaderActionButton(
label: '粘贴选手信息',
onPressed: () => onPasteEventInfo(),

View File

@@ -21,11 +21,15 @@ class RecordingHudWidget extends StatelessWidget {
required this.isTouchLocked,
this.showClipboardHint = false,
this.clipboardAddress = '',
required this.zoomRatio,
required this.minZoomRatio,
required this.maxZoomRatio,
required this.onStart,
required this.onStop,
required this.onOpenDnd,
required this.onOpenBattery,
required this.onToggleTouchLock,
required this.onZoomSelected,
});
final String? errorMessage;
@@ -38,16 +42,21 @@ class RecordingHudWidget extends StatelessWidget {
final bool isTouchLocked;
final bool showClipboardHint;
final String clipboardAddress;
final double zoomRatio;
final double minZoomRatio;
final double maxZoomRatio;
final Future<void> Function() onStart;
final Future<void> Function() onStop;
final VoidCallback onOpenDnd;
final VoidCallback onOpenBattery;
final VoidCallback onToggleTouchLock;
final ValueChanged<double> onZoomSelected;
static double get _recordButtonSize => 70.r;
static double get _recordButtonBottom => 63.r;
static double get _overlayInfoLeft => 13.r;
static double get _overlayInfoBottom => 10.r;
static const List<double> _zoomPresets = [1.0, 2.0, 3.0];
@override
Widget build(BuildContext context) {
@@ -133,6 +142,17 @@ class RecordingHudWidget extends StatelessWidget {
),
),
),
Positioned(
right: 16.r,
bottom: _recordButtonBottom + _recordButtonSize + 14.h,
child: _ZoomPresetControl(
zoomRatio: zoomRatio,
minZoomRatio: minZoomRatio,
maxZoomRatio: maxZoomRatio,
presets: _zoomPresets,
onSelected: onZoomSelected,
),
),
Positioned(
left: 0,
right: 0,
@@ -171,3 +191,94 @@ class RecordingHudWidget extends StatelessWidget {
);
}
}
class _ZoomPresetControl extends StatelessWidget {
const _ZoomPresetControl({
required this.zoomRatio,
required this.minZoomRatio,
required this.maxZoomRatio,
required this.presets,
required this.onSelected,
});
final double zoomRatio;
final double minZoomRatio;
final double maxZoomRatio;
final List<double> presets;
final ValueChanged<double> onSelected;
@override
Widget build(BuildContext context) {
final availablePresets = presets
.where((preset) => preset >= minZoomRatio && preset <= maxZoomRatio)
.toList(growable: false);
if (availablePresets.isEmpty) {
return const SizedBox.shrink();
}
return DecoratedBox(
decoration: BoxDecoration(
color: Colors.black.withValues(alpha: 0.46),
borderRadius: BorderRadius.circular(18.r),
border: Border.all(color: Colors.white.withValues(alpha: 0.18)),
),
child: Padding(
padding: EdgeInsets.all(3.r),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
for (final preset in availablePresets)
_ZoomPresetButton(
ratio: preset,
selected: (zoomRatio - preset).abs() < 0.05,
onSelected: onSelected,
),
],
),
),
);
}
}
class _ZoomPresetButton extends StatelessWidget {
const _ZoomPresetButton({
required this.ratio,
required this.selected,
required this.onSelected,
});
final double ratio;
final bool selected;
final ValueChanged<double> onSelected;
@override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.symmetric(horizontal: 1.r),
child: TextButton(
onPressed: selected ? null : () => onSelected(ratio),
style: TextButton.styleFrom(
minimumSize: Size(38.r, 32.r),
padding: EdgeInsets.zero,
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
foregroundColor: selected ? Colors.black : Colors.white,
disabledForegroundColor: Colors.black,
backgroundColor: selected ? Colors.white : Colors.transparent,
disabledBackgroundColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15.r),
),
),
child: Text(
'${ratio.toStringAsFixed(0)}x',
style: TextStyle(
fontSize: 13.sp,
fontWeight: FontWeight.w700,
letterSpacing: 0,
),
),
),
);
}
}