Reputation: 428
I'm working on an app that I need to implement zoom functionality with page swiping, in my case I need to make the zoom above the entire page view builder rather than on individual pages, similar to how the photo_view package works.
I am putting an Interactive widget above the page view builder like in the code below, I managed to prevent swiping while the user is zooming, but I'm struggling with re-enabling the swipe when the user reaches the edge of the screen while zoomed in and wants to navigate to the next page.
The issue is the dx value which am I getting from the matrix is always negative even if the user reaches the right or the left edge of the screen.
(note: dx value changed based on the zooming value but it is still negative).
How to detect that the user reaches the edge of the screen and needs to swipe to the next screen in the zooming case?
class ZoomWidget extends StatefulWidget {
const ZoomWidget({
super.key,
});
@override
State<ZoomWidget> createState() => _ZoomWidgetState();
}
class _ZoomWidgetState extends State<ZoomWidget> {
// _controller = StreamController<bool>();
late final ValueNotifier<bool> _isScaling;
// this is for removing scaling because first two pages contains zoom widget
bool _isAtEdge = false;
late final TransformationController _transformationController;
static const double _minScale = 1.0;
late final double width;
@override
void initState() {
_isScaling = ValueNotifier(false);
_transformationController = TransformationController();
width = MediaQuery.sizeOf(context).width;
super.initState();
}
@override
void dispose() {
_isScaling.dispose();
_transformationController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return InteractiveViewer(
panAxis: PanAxis.aligned,
transformationController: _transformationController,
maxScale: 3,
minScale: _minScale,
onInteractionUpdate: (details) {
// get the matrix
final Matrix4 matrix = _transformationController.value;
// get the scale
final double scale = matrix.getMaxScaleOnAxis();
// to update the physics
_isScaling.value = scale > _minScale;
},
onInteractionStart: (details) {
// get the matrix
final Matrix4 matrix = _transformationController.value;
// get the dx
final double dx = matrix.getTranslation().x;
// get the scale
final double scale = matrix.getMaxScaleOnAxis();
_isAtEdge = (dx < 0 && scale > _minScale);
//|| (dx < -width && scale > _minScale)
// log(_isAtEdge.toString());
},
child: GestureDetector(
child: ValueListenableBuilder(
valueListenable: _isScaling,
builder: (context, isScaling, child) {
return PageView.builder(
itemCount: 6,
physics: isScaling ? const NeverScrollableScrollPhysics() : const ClampingScrollPhysics(),
onPageChanged: (int index) {},
scrollDirection: Axis.horizontal,
itemBuilder: (context, index) {
return SomeWidget();
},
);
},
),
),
);
}
}
Upvotes: 0
Views: 105