From 09b22570f1bb0e8184e181a18fb6edff673c0d46 Mon Sep 17 00:00:00 2001 From: Carlit0 Date: Sat, 13 Apr 2019 02:23:06 +0200 Subject: [PATCH 1/7] setup extra Stream only for scaleState changes this is for better performance --- lib/src/photo_view_controller.dart | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/lib/src/photo_view_controller.dart b/lib/src/photo_view_controller.dart index d1268f76..ac232d81 100644 --- a/lib/src/photo_view_controller.dart +++ b/lib/src/photo_view_controller.dart @@ -18,9 +18,12 @@ typedef ScaleStateListener = void Function(double prevScale, double nextScale); /// /// The default implementation used by [PhotoView] is [PhotoViewController]. abstract class PhotoViewControllerBase { - /// The output for state updates. Usually a broadcast [Stream] + /// The output for state/value updates. Usually a broadcast [Stream] Stream get outputStateStream; + /// The output for scaleState changes [Stream] + Stream get outputScaleStateStream; + /// The state value before the last change or the initial state if trhe state has not been changed. T prevValue; @@ -122,22 +125,30 @@ class PhotoViewController _notifier.addListener(_changeListener); _outputCtrl = StreamController.broadcast(); _outputCtrl.sink.add(initial); + _outputScaleStateCtrl = StreamController(); + _outputScaleStateCtrl.sink.add(PhotoViewScaleState.initial); } ValueNotifier _notifier; PhotoViewControllerValue initial; StreamController _outputCtrl; + StreamController _outputScaleStateCtrl; @override Stream get outputStateStream => _outputCtrl.stream; + @override + Stream get outputScaleStateStream => + _outputScaleStateCtrl.stream; + @override PhotoViewControllerValue prevValue; @override void reset() { value = initial; + _outputScaleStateCtrl.sink.add(PhotoViewScaleState.initial); } void _changeListener() { @@ -147,6 +158,7 @@ class PhotoViewController @override void dispose() { _outputCtrl.close(); + _outputScaleStateCtrl.close(); _notifier.dispose(); } @@ -213,6 +225,7 @@ class PhotoViewController rotation: rotation, scaleState: scaleState, rotationFocusPoint: rotationFocusPoint); + _outputScaleStateCtrl.sink.add(scaleState); } @override @@ -245,6 +258,9 @@ class PhotoViewController Size outerSize, Size childSize, }) { + if (value.scaleState != scaleState) { + _outputScaleStateCtrl.sink.add(scaleState); + } prevValue = value; value = PhotoViewControllerValue( position: position ?? value.position, From f26071da5b55ca04eef1f571a92b1dedc3dbce3e Mon Sep 17 00:00:00 2001 From: Carlit0 Date: Sat, 13 Apr 2019 02:24:46 +0200 Subject: [PATCH 2/7] subscribe to the new Stream --- lib/photo_view.dart | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/lib/photo_view.dart b/lib/photo_view.dart index 8c13dd28..3b6e2d9d 100644 --- a/lib/photo_view.dart +++ b/lib/photo_view.dart @@ -299,7 +299,7 @@ class _PhotoViewState extends State _controlledController = false; controller = widget.controller; } - controller.outputStateStream.listen(scaleStateListener); + controller.outputScaleStateStream.listen(scaleStateListener); } @override @@ -341,9 +341,8 @@ class _PhotoViewState extends State } } - void scaleStateListener(PhotoViewControllerValue value) { - if (widget.scaleStateChangedCallback != null && - controller.scaleState != controller.prevValue.scaleState) { + void scaleStateListener(PhotoViewScaleState scaleState) { + if (widget.scaleStateChangedCallback != null) { widget.scaleStateChangedCallback(controller.scaleState); } } From e3c1d66cbb93774bc8054e031a3443c356c9f393 Mon Sep 17 00:00:00 2001 From: Carlit0 Date: Sat, 13 Apr 2019 02:30:47 +0200 Subject: [PATCH 3/7] introducing new ScaleStates: 'zoomedIn' and 'zoomedOut' --- lib/photo_view.dart | 3 ++- lib/photo_view_gallery.dart | 5 ++++- lib/src/photo_view_scale_state.dart | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/lib/photo_view.dart b/lib/photo_view.dart index 3b6e2d9d..d5334cce 100644 --- a/lib/photo_view.dart +++ b/lib/photo_view.dart @@ -448,7 +448,8 @@ PhotoViewScaleState defaultScaleStateCycle(PhotoViewScaleState actual) { return PhotoViewScaleState.originalSize; case PhotoViewScaleState.originalSize: return PhotoViewScaleState.initial; - case PhotoViewScaleState.zooming: + case PhotoViewScaleState.zoomedIn: + case PhotoViewScaleState.zoomedOut: return PhotoViewScaleState.initial; default: return PhotoViewScaleState.initial; diff --git a/lib/photo_view_gallery.dart b/lib/photo_view_gallery.dart index 566c6b48..11224bc1 100644 --- a/lib/photo_view_gallery.dart +++ b/lib/photo_view_gallery.dart @@ -170,7 +170,10 @@ class _PhotoViewGalleryState extends State { void scaleStateChangedCallback(PhotoViewScaleState scaleState) { setState(() { - _locked = scaleState != PhotoViewScaleState.initial; + _locked = (scaleState == PhotoViewScaleState.initial || + scaleState == PhotoViewScaleState.zoomedOut) + ? false + : true; }); if (widget.scaleStateChangedCallback != null) { widget.scaleStateChangedCallback(scaleState); diff --git a/lib/src/photo_view_scale_state.dart b/lib/src/photo_view_scale_state.dart index a61923df..fbe59be8 100644 --- a/lib/src/photo_view_scale_state.dart +++ b/lib/src/photo_view_scale_state.dart @@ -1,2 +1,2 @@ /// A way to represent the step of the "doubletap gesture cycle" in which PhotoView is. -enum PhotoViewScaleState { initial, covering, originalSize, zooming } +enum PhotoViewScaleState { initial, covering, originalSize, zooming, zoomedIn, zoomedOut} // 'zooming' will get unnecessary From bbbb38cff9903d0af453786bedef36590e183ce0 Mon Sep 17 00:00:00 2001 From: Carlit0 Date: Sat, 13 Apr 2019 02:39:36 +0200 Subject: [PATCH 4/7] adjust GestureDetector and imageWrapper if the user scales the image bigger than its initialScale the scaleState will be 'zoomedIn' ... otherwise -> 'zoomedOut' currently the trigger point is the initialScale at this point additional customization of the trigger point will be EASY --- lib/src/photo_view_image_wrapper.dart | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/lib/src/photo_view_image_wrapper.dart b/lib/src/photo_view_image_wrapper.dart index 0c6e1fb0..338d3663 100644 --- a/lib/src/photo_view_image_wrapper.dart +++ b/lib/src/photo_view_image_wrapper.dart @@ -110,9 +110,17 @@ class _PhotoViewImageWrapperState extends State void onScaleUpdate(ScaleUpdateDetails details) { final double newScale = _scaleBefore * details.scale; final Offset delta = details.focalPoint - _normalizedPosition; + + final double _scale = + widget.controller.scale ?? widget.scaleBoundaries.initialScale; + final double _initialScale = widget.scaleBoundaries.initialScale; + final PhotoViewScaleState newScaleState = details.scale != 1.0 - ? PhotoViewScaleState.zooming + ? (_scale > _initialScale) + ? PhotoViewScaleState.zoomedIn + : PhotoViewScaleState.zoomedOut : widget.controller.scaleState; + widget.controller.updateMultiple( scaleState: newScaleState, scale: newScale, @@ -249,7 +257,8 @@ class _PhotoViewImageWrapperState extends State void scaleStateListener(PhotoViewControllerValue value) { if (widget.controller.prevValue.scaleState != widget.controller.scaleState && - widget.controller.scaleState != PhotoViewScaleState.zooming) { + (widget.controller.scaleState != PhotoViewScaleState.zoomedIn && + widget.controller.scaleState != PhotoViewScaleState.zoomedOut)) { final double prevScale = widget.controller.scale ?? getScaleForScaleState( PhotoViewScaleState.initial, widget.scaleBoundaries); @@ -267,11 +276,11 @@ class _PhotoViewImageWrapperState extends State final ScaleBoundaries scaleBoundaries = widget.scaleBoundaries; final PhotoViewControllerBase controller = widget.controller; final PhotoViewScaleState scaleState = controller.scaleState; - if (scaleState == PhotoViewScaleState.zooming) { - controller.scaleState = widget.scaleStateCycle(scaleState); + if (scaleState == PhotoViewScaleState.zoomedIn || + scaleState == PhotoViewScaleState.zoomedOut) { + widget.controller.scaleState = widget.scaleStateCycle(scaleState); return; } - final double originalScale = getScaleForScaleState(scaleState, scaleBoundaries); From 947cc71267796ceed024316dd259e85e63519359 Mon Sep 17 00:00:00 2001 From: Carlit0 Date: Sat, 13 Apr 2019 16:19:30 +0200 Subject: [PATCH 5/7] formatted Enum --- lib/src/photo_view_scale_state.dart | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/src/photo_view_scale_state.dart b/lib/src/photo_view_scale_state.dart index fbe59be8..c577055a 100644 --- a/lib/src/photo_view_scale_state.dart +++ b/lib/src/photo_view_scale_state.dart @@ -1,2 +1,9 @@ /// A way to represent the step of the "doubletap gesture cycle" in which PhotoView is. -enum PhotoViewScaleState { initial, covering, originalSize, zooming, zoomedIn, zoomedOut} // 'zooming' will get unnecessary +enum PhotoViewScaleState { + initial, + covering, + originalSize, + zooming, + zoomedIn, + zoomedOut +} // 'zooming' will get unnecessary From ebae2ba67349b363f21d0ca9dc114d6b6d7c8151 Mon Sep 17 00:00:00 2001 From: Carlit0 Date: Tue, 16 Apr 2019 18:24:13 +0200 Subject: [PATCH 6/7] used 'newScale' --- lib/src/photo_view_image_wrapper.dart | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/src/photo_view_image_wrapper.dart b/lib/src/photo_view_image_wrapper.dart index 338d3663..8999e7cb 100644 --- a/lib/src/photo_view_image_wrapper.dart +++ b/lib/src/photo_view_image_wrapper.dart @@ -111,12 +111,10 @@ class _PhotoViewImageWrapperState extends State final double newScale = _scaleBefore * details.scale; final Offset delta = details.focalPoint - _normalizedPosition; - final double _scale = - widget.controller.scale ?? widget.scaleBoundaries.initialScale; final double _initialScale = widget.scaleBoundaries.initialScale; final PhotoViewScaleState newScaleState = details.scale != 1.0 - ? (_scale > _initialScale) + ? (newScale > _initialScale) ? PhotoViewScaleState.zoomedIn : PhotoViewScaleState.zoomedOut : widget.controller.scaleState; From 04a4997f14a028991e1278e3a46e87af038ddf0b Mon Sep 17 00:00:00 2001 From: Carlit0 Date: Tue, 16 Apr 2019 20:29:32 +0200 Subject: [PATCH 7/7] removed scaleState "zooming" --- .../screens/examples/controller_example.dart | 7 ++++--- lib/src/photo_view_controller.dart | 6 ++++-- lib/src/photo_view_scale_state.dart | 3 +-- lib/src/photo_view_utils.dart | 3 ++- test/controller_test.dart | 18 +++++++++++------- 5 files changed, 22 insertions(+), 15 deletions(-) diff --git a/example/lib/screens/examples/controller_example.dart b/example/lib/screens/examples/controller_example.dart index 96211af9..d44020d0 100644 --- a/example/lib/screens/examples/controller_example.dart +++ b/example/lib/screens/examples/controller_example.dart @@ -26,7 +26,7 @@ class _ControllerExampleState extends State { controller = PhotoViewController(); controller ..scale = defScale - ..scaleState = PhotoViewScaleState.zooming + ..scaleState = PhotoViewScaleState.initial ..outputStateStream.listen(onControllerState); super.initState(); } @@ -112,7 +112,6 @@ class _ControllerExampleState extends State { max: max, onChanged: (double newRotation) { controller.rotation = newRotation; - controller.scaleState = PhotoViewScaleState.zooming; })), Text( "Scale ${value.scale}", @@ -127,7 +126,9 @@ class _ControllerExampleState extends State { max: maxScale, onChanged: (double newScale) { controller.scale = newScale; - controller.scaleState = PhotoViewScaleState.zooming; + controller.scaleState = newScale > defScale + ? PhotoViewScaleState.zoomedIn + : PhotoViewScaleState.zoomedOut; })), ], ); diff --git a/lib/src/photo_view_controller.dart b/lib/src/photo_view_controller.dart index ac232d81..e196a756 100644 --- a/lib/src/photo_view_controller.dart +++ b/lib/src/photo_view_controller.dart @@ -41,7 +41,7 @@ abstract class PhotoViewControllerBase { /// The scale factor to transform the child (image or a customChild). /// - /// **Important**: Avoid setting this field without setting [scaleState] to [PhotoViewScaleState.zooming]. + /// **Important**: Avoid setting this field without setting [scaleState] to [PhotoViewScaleState.zoomedIn] or [PhotoViewScaleState.zoomedOut]. <- this has to be chnaged in the future double scale; /// The rotation factor to transform the child (image or a customChild). @@ -52,7 +52,8 @@ abstract class PhotoViewControllerBase { /// A way to represent the step of the "doubletap gesture cycle" in which PhotoView is. /// - /// **Important**: This fields is rarely externally set to a value different than [PhotoViewScaleState.zooming] after setting a [scale]. + /// **Important**: This fields is rarely externally set to a value different than [PhotoViewScaleState.zoomedIn] or [PhotoViewScaleState.zoomedOut] after setting a [scale]. + /// future TODO: setting the controller.scale should also set the scaleState to [PhotoViewScaleState.zoomedIn] or [PhotoViewScaleState.zoomedOut] PhotoViewScaleState scaleState; /// Update multiple fields of the state with only one update streamed. @@ -184,6 +185,7 @@ class PhotoViewController if (value.scale == scale) { return; } + prevValue = value; value = PhotoViewControllerValue( position: position, diff --git a/lib/src/photo_view_scale_state.dart b/lib/src/photo_view_scale_state.dart index c577055a..3b3f45fa 100644 --- a/lib/src/photo_view_scale_state.dart +++ b/lib/src/photo_view_scale_state.dart @@ -3,7 +3,6 @@ enum PhotoViewScaleState { initial, covering, originalSize, - zooming, zoomedIn, zoomedOut -} // 'zooming' will get unnecessary +} diff --git a/lib/src/photo_view_utils.dart b/lib/src/photo_view_utils.dart index 93f36862..e0347425 100644 --- a/lib/src/photo_view_utils.dart +++ b/lib/src/photo_view_utils.dart @@ -7,7 +7,8 @@ double getScaleForScaleState( PhotoViewScaleState scaleState, ScaleBoundaries scaleBoundaries) { switch (scaleState) { case PhotoViewScaleState.initial: - case PhotoViewScaleState.zooming: + case PhotoViewScaleState.zoomedIn: + case PhotoViewScaleState.zoomedOut: return _clampSize(scaleBoundaries.initialScale, scaleBoundaries); case PhotoViewScaleState.covering: return _clampSize( diff --git a/test/controller_test.dart b/test/controller_test.dart index 8479f892..fb4479de 100644 --- a/test/controller_test.dart +++ b/test/controller_test.dart @@ -38,8 +38,11 @@ void main() { controller.rotationFocusPoint = Offset.zero; expect(controller.rotationFocusPoint, Offset.zero); - controller.scaleState = PhotoViewScaleState.zooming; - expect(controller.scaleState, PhotoViewScaleState.zooming); + controller.scaleState = PhotoViewScaleState.zoomedIn; + expect(controller.scaleState, PhotoViewScaleState.zoomedIn); + + // controller.scaleState = PhotoViewScaleState.zoomedOut; + // expect(controller.scaleState, PhotoViewScaleState.zoomedOut); controller.updateMultiple( position: const Offset(1, 1), scaleState: PhotoViewScaleState.initial); @@ -63,35 +66,36 @@ void main() { scale: null, rotation: 0.0, rotationFocusPoint: null, - scaleState: PhotoViewScaleState.zooming); + scaleState: PhotoViewScaleState.zoomedOut); const PhotoViewControllerValue value2 = const PhotoViewControllerValue( position: Offset.zero, scale: null, rotation: 1.0, rotationFocusPoint: null, - scaleState: PhotoViewScaleState.zooming); + scaleState: PhotoViewScaleState.zoomedOut); const PhotoViewControllerValue value3 = const PhotoViewControllerValue( position: Offset.zero, scale: 3.0, rotation: 1.0, rotationFocusPoint: null, - scaleState: PhotoViewScaleState.zooming); + scaleState: PhotoViewScaleState.zoomedOut); const PhotoViewControllerValue value4 = const PhotoViewControllerValue( position: const Offset(1, 1), scale: 3.0, rotation: 45.0, rotationFocusPoint: null, - scaleState: PhotoViewScaleState.zooming); + scaleState: PhotoViewScaleState.zoomedOut); expect(controller.outputStateStream, emitsInOrder([value1, value2, value3, value4])); - controller.scaleState = PhotoViewScaleState.zooming; + controller.scaleState = PhotoViewScaleState.zoomedOut; controller.rotation = 1.0; controller.scale = 3.0; controller.updateMultiple(position: const Offset(1, 1), rotation: 45.0); + //Testing with 'zoomedIn' and 'zoomedOut' will be diffcult as long as scaleState isn't changed in the controller's scale setter }); }