终于解决了这个切换试题放大的内容乱跑的问题(更新视图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; // 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) final newMatrix = Matrix4.copy(currentMatrix)
@ -116,7 +117,7 @@ Widget $questionNumberScrollView({
currentMatrix.getTranslation().z, // Z currentMatrix.getTranslation().z, // Z
)); ));
controller.zoomController.value = newMatrix; controller.zoomController?.value = newMatrix;
}); });
var listenVal = sateData.slide.listen((e) { var listenVal = sateData.slide.listen((e) {
if (sateData.panQuestView != null && sateData.panQuestView == true && e != scrollControllerNum.offset) { if (sateData.panQuestView != null && sateData.panQuestView == true && e != scrollControllerNum.offset) {

View File

@ -46,10 +46,10 @@ class QuestionPaperView extends GetView<HomeworkReviewLogic> {
if (zoomFileModel == null) { if (zoomFileModel == null) {
/// ///
return LayoutBuilder(builder: (BuildContext context, BoxConstraints constraints) { return LayoutBuilder(builder: (BuildContext context, BoxConstraints constraints) {
WidgetsBinding.instance.addPostFrameCallback((_) => zoomState.zoomFile.value = ZoomFileModel( WidgetsBinding.instance.addPostFrameCallback(
viewWidth: constraints.maxWidth, (_) => zoomState.zoomFile.value =
viewHeight: constraints.maxHeight, ZoomFileModel(viewWidth: constraints.maxWidth, viewHeight: constraints.maxHeight),
)); );
return const SizedBox(); return const SizedBox();
}); });
} }
@ -345,7 +345,18 @@ class QuestionImageView extends HookWidget with EventBusMixin<BottomOperationBar
var zoomKey = useState<GlobalKey>(GlobalKey()); var zoomKey = useState<GlobalKey>(GlobalKey());
useValueChanged<int?, void>(zoomState.zoomFile.value?.templateId, (old, __) { useValueChanged<int?, void>(zoomState.zoomFile.value?.templateId, (old, __) {
// Zoom组件
WidgetsBinding.instance.addPostFrameCallback((_) {
zoomKey.value = GlobalKey(); 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>>([]); var vnHandWritings = useValueNotifier<List<dynamic>>([]);
@ -523,7 +534,7 @@ class QuestionImageView extends HookWidget with EventBusMixin<BottomOperationBar
Offset localPosition = event.localPosition; // Offset localPosition = event.localPosition; //
// 使 // 使
final Matrix4 matrix = logic.zoomController.value; // final Matrix4 matrix = logic.zoomController?.value ?? Matrix4.identity(); //
final double theScale = matrix.getMaxScaleOnAxis(); final double theScale = matrix.getMaxScaleOnAxis();
// if (theScale != 1) { // if (theScale != 1) {
// print("PPPPPPPPPPPPPPPPPPPPPPPP ${(zoomFile.imageHeightOffsetStart ?? 0)}"); // print("PPPPPPPPPPPPPPPPPPPPPPPP ${(zoomFile.imageHeightOffsetStart ?? 0)}");
@ -588,22 +599,7 @@ class QuestionImageView extends HookWidget with EventBusMixin<BottomOperationBar
child: IgnorePointer( child: IgnorePointer(
// Zoom // Zoom
ignoring: !annotationState.gestureMove.value, ignoring: !annotationState.gestureMove.value,
child: child: Zoom(
// 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, key: zoomKey.value,
// initTotalZoomOut: true, // // initTotalZoomOut: true, //
zoomSensibility: 0.05, zoomSensibility: 0.05,
@ -613,13 +609,13 @@ class QuestionImageView extends HookWidget with EventBusMixin<BottomOperationBar
maxZoomHeight: actualHeight, maxZoomHeight: actualHeight,
canvasColor: Colors.transparent, canvasColor: Colors.transparent,
doubleTapScaleChange: 1, doubleTapScaleChange: 1,
// initPosition: initPosition.value, initScale: 1,
// initScale: logic.zoomLogic.zoomState.initScale.value ?? 1,
backgroundColor: Colors.transparent, backgroundColor: Colors.transparent,
onScaleUpdate: (double scale, double zoom) => logic.zoomLogic.onScaleUpdate(zoom), // onScaleUpdate: (double scale, double zoom) => logic.zoomLogic.onScaleUpdate(zoom),
onPositionUpdate: logic.zoomLogic.onPanUpPosition, // onPositionUpdate: logic.zoomLogic.onPanUpPosition,
transformationController: logic.zoomController, transformationController: logic.zoomController,
child: Stack( child: Obx(() {
return Stack(
children: [ children: [
$TheCachedNetworkImage( $TheCachedNetworkImage(
imgWidth: maxWidth, imgWidth: maxWidth,
@ -646,9 +642,10 @@ class QuestionImageView extends HookWidget with EventBusMixin<BottomOperationBar
), ),
), ),
], ],
);
}),
), ),
), ),
)),
); );
}), }),
); );

View File

@ -83,7 +83,7 @@ class HomeworkReviewLogic extends GetxController with RequestToolMixin, EventBus
StreamSubscription<TestQuestionsImageInfo?>? imageScaleZoomStream; StreamSubscription<TestQuestionsImageInfo?>? imageScaleZoomStream;
late final zoomWidget.TransformationController zoomController; zoomWidget.TransformationController? zoomController;
@override @override
void onInit() { void onInit() {
@ -105,15 +105,6 @@ class HomeworkReviewLogic extends GetxController with RequestToolMixin, EventBus
// //
_dataListen = state.data.listen((e) { _dataListen = state.data.listen((e) {
if (e == null) return; 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; if (state.favorite.value != e.isFav) state.favorite.value = !state.favorite.value;
}); });
@ -147,7 +138,7 @@ class HomeworkReviewLogic extends GetxController with RequestToolMixin, EventBus
@override @override
void onClose() { void onClose() {
zoomController.dispose(); zoomController?.dispose();
// SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: [SystemUiOverlay.top]); // // SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: [SystemUiOverlay.top]); //
eventCancel(); eventCancel();
_dataListen.cancel(); _dataListen.cancel();

View File

@ -17,47 +17,44 @@ class ZoomLogic extends GetxController {
); );
var oldTemplateId; var oldTemplateId;
late StreamSubscription _streamHomework; StreamSubscription? _streamHomework;
late StreamSubscription _streamZoomState; StreamSubscription? _streamZoomState;
StreamSubscription<double?>? initScaleStream; StreamSubscription<double?>? initScaleStream;
Map<int, ZoomFileModel> imageSizeMap = {};
HomeworkReviewLogic get homeworkReviewLogic => Get.find<HomeworkReviewLogic>();
@override @override
void onInit() { void onInit() {
oldTemplateId = zoomState.zoomFile.value?.templateId; oldTemplateId = zoomState.zoomFile.value?.templateId;
/// ///
_streamZoomState = zoomState.zoomFile.listen((e) { _streamZoomState = zoomState.zoomFile.listen((e) => refreshZoomFile(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());
});
});
WidgetsBinding.instance.addPostFrameCallback((e) { WidgetsBinding.instance.addPostFrameCallback((e) {
/// ///
_streamHomework = Get.find<HomeworkReviewLogic>().state.data.listen((e) { _streamHomework = homeworkReviewLogic.state.data.listen((e) {
print("HOMEWORKSTATE 变化了"); print("HOMEWORKSTATE 变化了");
if (e == null || zoomState.zoomFile.value == null) return; var zoomFile = zoomState.zoomFile.value;
zoomState.zoomFile.value!.templateId = e.templateId; if (e == null || zoomFile == null) return;
print("666666 ${e.templateId}");
zoomState.zoomFile.value = ZoomFileModel.fromJson(zoomState.zoomFile.value!.toJson()); 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 @override
void onClose() { void onClose() {
_streamHomework.cancel(); _streamHomework?.cancel();
_streamZoomState.cancel(); _streamZoomState?.cancel();
super.onClose(); 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 { void onScaleUpdate(double zoom) async {
print("缩放比例:$zoom"); print("缩放比例:$zoom");
@ -86,12 +123,34 @@ class ZoomLogic extends GetxController {
// ==> // ==>
void onPanUpPosition(Offset val) async { void onPanUpPosition(Offset val) async {
// //
var state = Get.find<HomeworkReviewLogic>().state; var state = homeworkReviewLogic.state;
print('**************** 正在移动位置 YYY:${val.dy}'); print('**************** 正在移动位置 YYY:${val.dy}');
print('**************** 正在移动位置 XXX:${val.dx}'); print('**************** 正在移动位置 XXX:${val.dx}');
state.zoomOffset = val; state.zoomOffset = val;
state.slide.value = val.dy.abs().toInt().toDouble(); 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 { class HomeworkReviewZoomBinding extends Bindings {
@ -143,9 +202,9 @@ class ZoomFileModel extends Object {
this.imageHeightOffsetend, this.imageHeightOffsetend,
this.pixelRatio, this.pixelRatio,
}) { }) {
///
// . // .
if (fileHeight == null || fileWidth == null) return; if (fileHeight != null && fileWidth != null) {
scaleRatio = viewWidth / fileWidth!; scaleRatio = viewWidth / fileWidth!;
actualWidth = fileWidth! * scaleRatio; actualWidth = fileWidth! * scaleRatio;
actualHeight = fileHeight! * scaleRatio; actualHeight = fileHeight! * scaleRatio;
@ -156,6 +215,7 @@ class ZoomFileModel extends Object {
imageHeightOffsetStart = remainingHeight! / 2; imageHeightOffsetStart = remainingHeight! / 2;
imageHeightOffsetend = imageHeightOffsetStart! + actualHeight!; imageHeightOffsetend = imageHeightOffsetStart! + actualHeight!;
} }
}
factory ZoomFileModel.fromJson(Map<String, dynamic> srcJson) => _$ZoomFileModelFromJson(srcJson); factory ZoomFileModel.fromJson(Map<String, dynamic> srcJson) => _$ZoomFileModelFromJson(srcJson);

View File

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