终于解决了这个切换试题放大的内容乱跑的问题(更新视图zoomController位置重置时机应在key重新后,不该在前,被覆盖)

This commit is contained in:
DESKTOP-I3JPKHK\wy 2025-09-28 18:07:50 +08:00
parent bac6a7410a
commit f050263ddf
5 changed files with 174 additions and 124 deletions

View File

@ -106,7 +106,8 @@ Widget $questionNumberScrollView({
///
// if (sateData.panQuestView == false) sateData.slide.value = scrollControllerNum.offset;
final currentMatrix = controller.zoomController.value;
final currentMatrix = controller.zoomController?.value;
if (currentMatrix == null) return;
//
final newMatrix = Matrix4.copy(currentMatrix)
@ -116,7 +117,7 @@ Widget $questionNumberScrollView({
currentMatrix.getTranslation().z, // Z
));
controller.zoomController.value = newMatrix;
controller.zoomController?.value = newMatrix;
});
var listenVal = sateData.slide.listen((e) {
if (sateData.panQuestView != null && sateData.panQuestView == true && e != scrollControllerNum.offset) {

View File

@ -46,10 +46,10 @@ class QuestionPaperView extends GetView<HomeworkReviewLogic> {
if (zoomFileModel == null) {
///
return LayoutBuilder(builder: (BuildContext context, BoxConstraints constraints) {
WidgetsBinding.instance.addPostFrameCallback((_) => zoomState.zoomFile.value = ZoomFileModel(
viewWidth: constraints.maxWidth,
viewHeight: constraints.maxHeight,
));
WidgetsBinding.instance.addPostFrameCallback(
(_) => zoomState.zoomFile.value =
ZoomFileModel(viewWidth: constraints.maxWidth, viewHeight: constraints.maxHeight),
);
return const SizedBox();
});
}
@ -345,7 +345,18 @@ class QuestionImageView extends HookWidget with EventBusMixin<BottomOperationBar
var zoomKey = useState<GlobalKey>(GlobalKey());
useValueChanged<int?, void>(zoomState.zoomFile.value?.templateId, (old, __) {
zoomKey.value = GlobalKey();
// Zoom组件
WidgetsBinding.instance.addPostFrameCallback((_) {
zoomKey.value = GlobalKey();
//
WidgetsBinding.instance.addPostFrameCallback((_) {
final double offsetY = (zoomState.zoomFile.value?.imageHeightOffsetStart ?? 0).toDouble();
if (offsetY > 0) {
logic.zoomController?.value = Matrix4.identity()..setTranslationRaw(0, offsetY, 0);
}
});
});
});
var vnHandWritings = useValueNotifier<List<dynamic>>([]);
@ -523,7 +534,7 @@ class QuestionImageView extends HookWidget with EventBusMixin<BottomOperationBar
Offset localPosition = event.localPosition; //
// 使
final Matrix4 matrix = logic.zoomController.value; //
final Matrix4 matrix = logic.zoomController?.value ?? Matrix4.identity(); //
final double theScale = matrix.getMaxScaleOnAxis();
// if (theScale != 1) {
// print("PPPPPPPPPPPPPPPPPPPPPPPP ${(zoomFile.imageHeightOffsetStart ?? 0)}");
@ -586,69 +597,55 @@ class QuestionImageView extends HookWidget with EventBusMixin<BottomOperationBar
width: double.infinity,
alignment: Alignment.center,
child: IgnorePointer(
// Zoom
ignoring: !annotationState.gestureMove.value,
child:
// ZoomView(
// key: zoomKey.value,
// viewWidth: maxWidth,
// viewHeight: maxHeight,
// imageDisplayHeight: actualHeight,
// url: sateData.data.value!.zgtAnswer,
// onScale: logic.zoomLogic.onScaleUpdate,
// // onTrans: (offset) {
// // print("偏移位置:$offset");
// // },
// onContentOffset: logic.zoomLogic.onPanUpPosition,
// ),
Obx(
() => Zoom(
key: zoomKey.value,
// initTotalZoomOut: true, //
zoomSensibility: 0.05,
scrollWeight: 4.r,
doubleTapAnimDuration: Duration.zero,
maxZoomWidth: maxWidth,
maxZoomHeight: actualHeight,
canvasColor: Colors.transparent,
doubleTapScaleChange: 1,
// initPosition: initPosition.value,
// initScale: logic.zoomLogic.zoomState.initScale.value ?? 1,
backgroundColor: Colors.transparent,
onScaleUpdate: (double scale, double zoom) => logic.zoomLogic.onScaleUpdate(zoom),
onPositionUpdate: logic.zoomLogic.onPanUpPosition,
transformationController: logic.zoomController,
child: Stack(
children: [
$TheCachedNetworkImage(
imgWidth: maxWidth,
imageUrl: sateData.data.value!.zgtAnswer,
(_, imageProvider) => Image(image: imageProvider, fit: BoxFit.fitWidth),
// Zoom
ignoring: !annotationState.gestureMove.value,
child: Zoom(
key: zoomKey.value,
// initTotalZoomOut: true, //
zoomSensibility: 0.05,
scrollWeight: 4.r,
doubleTapAnimDuration: Duration.zero,
maxZoomWidth: maxWidth,
maxZoomHeight: actualHeight,
canvasColor: Colors.transparent,
doubleTapScaleChange: 1,
initScale: 1,
backgroundColor: Colors.transparent,
// onScaleUpdate: (double scale, double zoom) => logic.zoomLogic.onScaleUpdate(zoom),
// onPositionUpdate: logic.zoomLogic.onPanUpPosition,
transformationController: logic.zoomController,
child: Obx(() {
return Stack(
children: [
$TheCachedNetworkImage(
imgWidth: maxWidth,
imageUrl: sateData.data.value!.zgtAnswer,
(_, imageProvider) => Image(image: imageProvider, fit: BoxFit.fitWidth),
),
RepaintBoundary(
key: logic.pictureOverviewKey,
child: CustomPaint(
// isComplex: true,
size: Size(maxWidth, actualHeight),
foregroundPainter: DrawingPainter(ctrl: vnHandWritings),
// child: $TheCachedNetworkImage(
// imgWidth: maxWidth,
// imageUrl: showZgtAnnotate ?? sateData.data.value!.zgtAnswer,
// (_, imageProvider) => Image(image: imageProvider, fit: BoxFit.fitWidth),
// ),
child: showZgtAnnotate != null
? $TheCachedNetworkImage(
imgWidth: maxWidth,
imageUrl: showZgtAnnotate,
(_, imageProvider) => Image(image: imageProvider, fit: BoxFit.fitWidth))
: null,
),
RepaintBoundary(
key: logic.pictureOverviewKey,
child: CustomPaint(
// isComplex: true,
size: Size(maxWidth, actualHeight),
foregroundPainter: DrawingPainter(ctrl: vnHandWritings),
// child: $TheCachedNetworkImage(
// imgWidth: maxWidth,
// imageUrl: showZgtAnnotate ?? sateData.data.value!.zgtAnswer,
// (_, imageProvider) => Image(image: imageProvider, fit: BoxFit.fitWidth),
// ),
child: showZgtAnnotate != null
? $TheCachedNetworkImage(
imgWidth: maxWidth,
imageUrl: showZgtAnnotate,
(_, imageProvider) => Image(image: imageProvider, fit: BoxFit.fitWidth))
: null,
),
),
],
),
),
)),
),
],
);
}),
),
),
);
}),
);

View File

@ -83,7 +83,7 @@ class HomeworkReviewLogic extends GetxController with RequestToolMixin, EventBus
StreamSubscription<TestQuestionsImageInfo?>? imageScaleZoomStream;
late final zoomWidget.TransformationController zoomController;
zoomWidget.TransformationController? zoomController;
@override
void onInit() {
@ -105,15 +105,6 @@ class HomeworkReviewLogic extends GetxController with RequestToolMixin, EventBus
//
_dataListen = state.data.listen((e) {
if (e == null) return;
var zoomState = zoomLogic.zoomState;
final currentTemplateId = zoomState.zoomFile.value?.templateId; // ID
if (currentTemplateId != null && currentTemplateId != e.templateId) {
// zoom zoom文件
zoomState.initScale.value = null;
zoomState.zoomFile.value!.clearZoomFile(e.templateId);
zoomState.zoomFile.update((_) {}); //
}
if (state.favorite.value != e.isFav) state.favorite.value = !state.favorite.value;
});
@ -147,7 +138,7 @@ class HomeworkReviewLogic extends GetxController with RequestToolMixin, EventBus
@override
void onClose() {
zoomController.dispose();
zoomController?.dispose();
// SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: [SystemUiOverlay.top]); //
eventCancel();
_dataListen.cancel();

View File

@ -17,47 +17,44 @@ class ZoomLogic extends GetxController {
);
var oldTemplateId;
late StreamSubscription _streamHomework;
late StreamSubscription _streamZoomState;
StreamSubscription? _streamHomework;
StreamSubscription? _streamZoomState;
StreamSubscription<double?>? initScaleStream;
Map<int, ZoomFileModel> imageSizeMap = {};
HomeworkReviewLogic get homeworkReviewLogic => Get.find<HomeworkReviewLogic>();
@override
void onInit() {
oldTemplateId = zoomState.zoomFile.value?.templateId;
///
_streamZoomState = zoomState.zoomFile.listen((e) {
var templateId = e?.templateId;
if (templateId == null) return;
var homeworkData = Get.find<HomeworkReviewLogic>().state.data.value;
var zgtAnswer = homeworkData?.zgtAnswer;
if (zgtAnswer == null) return;
if (oldTemplateId == templateId) return;
// getNetworkImageDimensions(zgtAnswer);
//
oldTemplateId = templateId;
CachedNetworkImageProvider(zgtAnswer).getImageSize().then((s) {
//
if (s == null) return;
var oldVal = zoomState.zoomFile.value!;
oldVal.fileWidth = s.width;
oldVal.fileHeight = s.height;
zoomState.zoomFile.value = ZoomFileModel.fromJson(oldVal.toJson());
});
});
_streamZoomState = zoomState.zoomFile.listen((e) => refreshZoomFile(e));
WidgetsBinding.instance.addPostFrameCallback((e) {
///
_streamHomework = Get.find<HomeworkReviewLogic>().state.data.listen((e) {
_streamHomework = homeworkReviewLogic.state.data.listen((e) {
print("HOMEWORKSTATE 变化了");
if (e == null || zoomState.zoomFile.value == null) return;
zoomState.zoomFile.value!.templateId = e.templateId;
print("666666 ${e.templateId}");
zoomState.zoomFile.value = ZoomFileModel.fromJson(zoomState.zoomFile.value!.toJson());
var zoomFile = zoomState.zoomFile.value;
if (e == null || zoomFile == null) return;
if (zoomFile.templateId != e.templateId) {
// zoom zoom文件
zoomState.initScale.value = null;
zoomFile = ZoomFileModel(
templateId: e.templateId,
viewWidth: zoomFile.viewWidth,
viewHeight: zoomFile.viewHeight,
);
///
_resetZoom();
}
///
refreshZoomFile(zoomFile);
});
});
@ -69,11 +66,51 @@ class ZoomLogic extends GetxController {
@override
void onClose() {
_streamHomework.cancel();
_streamZoomState.cancel();
_streamHomework?.cancel();
_streamZoomState?.cancel();
super.onClose();
}
void refreshZoomFile(ZoomFileModel? e) {
var templateId = e?.templateId;
if (templateId == null) return;
var homeworkData = homeworkReviewLogic.state.data.value;
var zgtAnswer = homeworkData?.zgtAnswer;
if (zgtAnswer == null || oldTemplateId == templateId) return;
// getNetworkImageDimensions(zgtAnswer);
oldTemplateId = templateId;
final fileSize = imageSizeMap[templateId];
print("fileSize: ${fileSize?.toJson()}");
if (fileSize != null) {
zoomState.zoomFile.value = fileSize;
return;
}
///
CachedNetworkImageProvider(zgtAnswer).getImageSize().then((s) {
if (s == null) return;
//
var oldZoomFile = zoomState.zoomFile.value!;
///
var newZoomFile = ZoomFileModel(
templateId: templateId,
viewWidth: oldZoomFile.viewWidth,
viewHeight: oldZoomFile.viewHeight,
fileWidth: s.width,
fileHeight: s.height,
);
/// zoom文件
imageSizeMap[templateId] = newZoomFile;
zoomState.zoomFile.value = newZoomFile;
});
}
// ==>
void onScaleUpdate(double zoom) async {
print("缩放比例:$zoom");
@ -86,12 +123,34 @@ class ZoomLogic extends GetxController {
// ==>
void onPanUpPosition(Offset val) async {
//
var state = Get.find<HomeworkReviewLogic>().state;
var state = homeworkReviewLogic.state;
print('**************** 正在移动位置 YYY:${val.dy}');
print('**************** 正在移动位置 XXX:${val.dx}');
state.zoomOffset = val;
state.slide.value = val.dy.abs().toInt().toDouble();
}
//
void _resetZoom() {
//
zoomState.initScale.value = 1.0;
//
homeworkReviewLogic.state.zoomOffset = Offset.zero;
homeworkReviewLogic.state.slide.value = 0.0;
// final zoomFile = zoomState.zoomFile.value;
// final double imageOffsetY = (zoomFile?.imageHeightOffsetStart ?? 0).toDouble();
// final controller = homeworkReviewLogic.zoomController;
// if (controller != null) {
// //
// final Matrix4 centered = Matrix4.identity()..setTranslationRaw(0, imageOffsetY > 0 ? imageOffsetY : 0, 0);
// controller.value = centered;
// }
print('缩放已重置');
}
}
class HomeworkReviewZoomBinding extends Bindings {
@ -143,18 +202,19 @@ class ZoomFileModel extends Object {
this.imageHeightOffsetend,
this.pixelRatio,
}) {
///
// .
if (fileHeight == null || fileWidth == null) return;
if (fileHeight != null && fileWidth != null) {
scaleRatio = viewWidth / fileWidth!;
actualWidth = fileWidth! * scaleRatio;
actualHeight = fileHeight! * scaleRatio;
scaleRatio = viewWidth / fileWidth!;
actualWidth = fileWidth! * scaleRatio;
actualHeight = fileHeight! * scaleRatio;
pixelRatio = fileWidth! / viewWidth; //
pixelRatio = fileWidth! / viewWidth; //
remainingHeight = viewHeight - actualHeight!;
imageHeightOffsetStart = remainingHeight! / 2;
imageHeightOffsetend = imageHeightOffsetStart! + actualHeight!;
remainingHeight = viewHeight - actualHeight!;
imageHeightOffsetStart = remainingHeight! / 2;
imageHeightOffsetend = imageHeightOffsetStart! + actualHeight!;
}
}
factory ZoomFileModel.fromJson(Map<String, dynamic> srcJson) => _$ZoomFileModelFromJson(srcJson);

View File

@ -48,7 +48,7 @@ dependencies:
# http请求插件
dio: ^5.4.2+1
# 网络缓存图片
cached_network_image: ^3.2.1
cached_network_image: ^3.4.1
# 上拉加载和下拉刷新的组件
flutter_easyrefresh: ^2.2.2
photo_view: ^0.15.0
@ -94,7 +94,7 @@ dependencies:
flutter_spinkit: ^5.2.1
event_bus: ^2.0.0
path_provider: ^2.1.3
uuid: ^3.0.7
flutter_echarts: ^2.4.0
# 饼图
flutter_echart: ^2.0.0
@ -112,6 +112,7 @@ dependencies:
dependency_overrides:
archive: ^4.0.2
uuid: ^4.4.2
# meta: ^1.15.0
dev_dependencies: