Skip to content

Commit

Permalink
Let user scroll to next page when PageView child is zooming (bluefire…
Browse files Browse the repository at this point in the history
  • Loading branch information
hongyun committed Aug 8, 2019
1 parent 57e1fab commit 24c7214
Show file tree
Hide file tree
Showing 7 changed files with 479 additions and 54 deletions.
124 changes: 81 additions & 43 deletions example/lib/screens/examples/gallery/gallery_example.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,13 @@ import 'package:photo_view/photo_view_gallery.dart';
import 'package:photo_view_example/screens/app_bar.dart';
import 'package:photo_view_example/screens/examples/gallery/gallery_example_item.dart';

class GalleryExample extends StatelessWidget {
void open(BuildContext context, final int index) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => GalleryPhotoViewWrapper(
galleryItems: galleryItems,
backgroundDecoration: const BoxDecoration(
color: Colors.black,
),
initialIndex: index,
),
));
}
class GalleryExample extends StatefulWidget {
@override
_GalleryExampleState createState() => _GalleryExampleState();
}

class _GalleryExampleState extends State<GalleryExample> {
bool useCustomPageView = true;

@override
Widget build(BuildContext context) {
Expand All @@ -32,38 +25,74 @@ class GalleryExample extends StatelessWidget {
),
Expanded(
child: Center(
child: Row(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
GalleryExampleItemThumbnail(
galleryExampleItem: galleryItems[0],
onTap: () {
open(context, 0);
},
),
GalleryExampleItemThumbnail(
galleryExampleItem: galleryItems[2],
onTap: () {
open(context, 2);
},
),
GalleryExampleItemThumbnail(
galleryExampleItem: galleryItems[3],
onTap: () {
open(context, 3);
},
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
GalleryExampleItemThumbnail(
galleryExampleItem: galleryItems[0],
onTap: () {
open(context, 0);
},
),
GalleryExampleItemThumbnail(
galleryExampleItem: galleryItems[2],
onTap: () {
open(context, 2);
},
),
GalleryExampleItemThumbnail(
galleryExampleItem: galleryItems[3],
onTap: () {
open(context, 3);
},
),
],
),
Container(
height: 30,
child: Center(
child: Row(
children: <Widget>[
const Text(" use custom pageView"),
Checkbox(
value: useCustomPageView,
onChanged: (value) {
setState(() {
useCustomPageView = value;
});
}),
],
))),
],
))),
],
),
);
}

void open(BuildContext context, final int index) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => GalleryPhotoViewWrapper(
usePageViewWrapper: useCustomPageView,
galleryItems: galleryItems,
backgroundDecoration: const BoxDecoration(
color: Colors.black,
),
initialIndex: index,
),
));
}
}

class GalleryPhotoViewWrapper extends StatefulWidget {
GalleryPhotoViewWrapper(
{this.loadingChild,
this.usePageViewWrapper = false,
this.backgroundDecoration,
this.minScale,
this.maxScale,
Expand All @@ -78,6 +107,7 @@ class GalleryPhotoViewWrapper extends StatefulWidget {
final int initialIndex;
final PageController pageController;
final List<GalleryExampleItem> galleryItems;
final bool usePageViewWrapper;

@override
State<StatefulWidget> createState() {
Expand All @@ -87,16 +117,19 @@ class GalleryPhotoViewWrapper extends StatefulWidget {

class _GalleryPhotoViewWrapperState extends State<GalleryPhotoViewWrapper> {
int currentIndex;

@override
void initState() {
currentIndex = widget.initialIndex;
super.initState();
}

void onPageChanged(int index) {
setState(() {
currentIndex = index;
});
if(!widget.usePageViewWrapper){
setState(() {
currentIndex = index;
});
}
}

@override
Expand All @@ -118,15 +151,20 @@ class _GalleryPhotoViewWrapperState extends State<GalleryPhotoViewWrapper> {
backgroundDecoration: widget.backgroundDecoration,
pageController: widget.pageController,
onPageChanged: onPageChanged,
usePageViewWrapper: widget.usePageViewWrapper,
),
Container(
padding: const EdgeInsets.all(20.0),
child: Text(
"Image ${currentIndex + 1}",
style: const TextStyle(
color: Colors.white, fontSize: 17.0, decoration: null),
),
)
widget.usePageViewWrapper
? Container()
: Container(
padding: const EdgeInsets.all(20.0),
child: Text(
"Image ${currentIndex + 1}",
style: const TextStyle(
color: Colors.white,
fontSize: 17.0,
decoration: null),
),
)
],
)),
);
Expand Down
5 changes: 5 additions & 0 deletions lib/photo_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,7 @@ class PhotoView extends StatefulWidget {
this.scaleStateCycle,
this.onTapUp,
this.onTapDown,
this.index,
}) : child = null,
childSize = null,
super(key: key);
Expand Down Expand Up @@ -263,11 +264,13 @@ class PhotoView extends StatefulWidget {
this.scaleStateCycle,
this.onTapUp,
this.onTapDown,
this.index,
}) : loadingChild = null,
imageProvider = null,
gaplessPlayback = false,
super(key: key);

int index;
/// Given a [imageProvider] it resolves into an zoomable image widget using. It
/// is required
final ImageProvider imageProvider;
Expand Down Expand Up @@ -480,6 +483,7 @@ class _PhotoViewState extends State<PhotoView>

Widget _buildCustomChild(BuildContext context) {
return PhotoViewImageWrapper.customChild(
index: widget.index,
customChild: widget.child,
backgroundDecoration: widget.backgroundDecoration,
enableRotation: widget.enableRotation,
Expand Down Expand Up @@ -529,6 +533,7 @@ class _PhotoViewState extends State<PhotoView>

Widget _buildWrapperImage(BuildContext context) {
return PhotoViewImageWrapper(
index: widget.index,
imageProvider: widget.imageProvider,
backgroundDecoration: widget.backgroundDecoration,
gaplessPlayback: widget.gaplessPlayback,
Expand Down
55 changes: 48 additions & 7 deletions lib/photo_view_gallery.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import 'package:photo_view/photo_view.dart';
import 'package:photo_view/src/photo_view_controller.dart';
import 'package:photo_view/src/photo_view_image_wrapper.dart';
import 'package:photo_view/src/photo_view_scale_state.dart';
import 'package:photo_view/src/photo_view_pageview_wrapper.dart';

/// A type definition for a [Function] that receives a index after a page change in [PhotoViewGallery]
typedef PhotoViewGalleryPageChangedCallback = void Function(int index);
Expand Down Expand Up @@ -83,6 +84,7 @@ class PhotoViewGallery extends StatefulWidget {
this.transitionOnUserGestures = false,
this.scrollPhysics,
this.scrollDirection = Axis.horizontal,
this.usePageViewWrapper = false,
}) : _isBuilder = false,
itemCount = null,
builder = null,
Expand All @@ -108,6 +110,7 @@ class PhotoViewGallery extends StatefulWidget {
this.transitionOnUserGestures = false,
this.scrollPhysics,
this.scrollDirection = Axis.horizontal,
this.usePageViewWrapper = false,
}) : _isBuilder = true,
pageOptions = null,
assert(itemCount != null),
Expand Down Expand Up @@ -161,6 +164,9 @@ class PhotoViewGallery extends StatefulWidget {

final bool _isBuilder;

///A bool indicate to use [PageViewWrapper]
final bool usePageViewWrapper;

@override
State<StatefulWidget> createState() {
return _PhotoViewGalleryState();
Expand All @@ -179,12 +185,15 @@ class _PhotoViewGalleryState extends State<PhotoViewGallery> {
}

void scaleStateChangedCallback(PhotoViewScaleState scaleState) {
setState(() {
_locked = (scaleState == PhotoViewScaleState.initial ||
scaleState == PhotoViewScaleState.zoomedOut)
? false
: true;
});
if (!widget.usePageViewWrapper) {
setState(() {
_locked = (scaleState == PhotoViewScaleState.initial ||
scaleState == PhotoViewScaleState.zoomedOut)
? false
: true;
});
}

if (widget.scaleStateChangedCallback != null) {
widget.scaleStateChangedCallback(scaleState);
}
Expand All @@ -203,6 +212,36 @@ class _PhotoViewGalleryState extends State<PhotoViewGallery> {

@override
Widget build(BuildContext context) {
return widget.usePageViewWrapper? _getPageViewWrapper(): _getPageView();
}

PageViewWrapper _getPageViewWrapper() {
debugPrint("_getPageViewWrapper");
final pageChangeListeners = OnPageChangedWrapper();
pageChangeListeners.addListener(widget.onPageChanged);

final customController = PageViewWrapperController(
pageViewController: _controller,
onPageChangedWrapper: pageChangeListeners);

final pageView = PageView.builder(
reverse: widget.reverse,
controller: _controller,
onPageChanged: pageChangeListeners.onPageChanged,
itemCount: itemCount,
itemBuilder: _buildItem,
scrollDirection: widget.scrollDirection,
physics:
_locked ? const NeverScrollableScrollPhysics() : widget.scrollPhysics,
);

return PageViewWrapper(
pageView: pageView,
controller: customController,
);
}

PageView _getPageView() {
return PageView.builder(
reverse: widget.reverse,
controller: _controller,
Expand All @@ -211,7 +250,7 @@ class _PhotoViewGalleryState extends State<PhotoViewGallery> {
itemBuilder: _buildItem,
scrollDirection: widget.scrollDirection,
physics:
_locked ? const NeverScrollableScrollPhysics() : widget.scrollPhysics,
_locked ? const NeverScrollableScrollPhysics() : widget.scrollPhysics,
);
}

Expand All @@ -222,6 +261,7 @@ class _PhotoViewGalleryState extends State<PhotoViewGallery> {
final PhotoView photoView = isCustomChild
? PhotoView.customChild(
key: ObjectKey(index),
index:index,
child: pageOption.child,
childSize: pageOption.childSize,
backgroundDecoration: widget.backgroundDecoration,
Expand All @@ -241,6 +281,7 @@ class _PhotoViewGalleryState extends State<PhotoViewGallery> {
)
: PhotoView(
key: ObjectKey(index),
index:index,
imageProvider: pageOption.imageProvider,
loadingChild: widget.loadingChild,
backgroundDecoration: widget.backgroundDecoration,
Expand Down
38 changes: 36 additions & 2 deletions lib/src/photo_view_controller_delegate.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class PhotoViewControllerDelegate {
final ScaleBoundaries scaleBoundaries;
final ScaleStateCycle scaleStateCycle;
final Alignment basePosition;

OffsetWrapper _lastOffsetWrapper;
Function(double prevScale, double nextScale) _animateScale;

void startListeners() {
Expand Down Expand Up @@ -163,7 +163,27 @@ class PhotoViewControllerDelegate {
final double computedY =
screenHeight < computedHeight ? y.clamp(minY, maxY) : 0.0;

return Offset(computedX, computedY);
final position = Offset(computedX, computedY);
final result = OffsetWrapper(position, x < minX, x > maxX);
_lastOffsetWrapper = result;
return position;
}

bool canMove(double scale, Offset delta) {
if(scale!=1.0) {
//when child is zooming
return true;
}
if (_lastOffsetWrapper != null) {
final moveRight = delta.dx < 0;
if (_lastOffsetWrapper.reachLeftBound) {
return moveRight;
} else if (_lastOffsetWrapper.reachRightBound) {
return !moveRight;
}
}

return scaleStateController.scaleState!=PhotoViewScaleState.initial;
}

void dispose() {
Expand All @@ -172,3 +192,17 @@ class PhotoViewControllerDelegate {
scaleStateController.removeIgnorableListener(_blindScaleStateListener);
}
}

class OffsetWrapper {
OffsetWrapper(
this.position, this.reachRightBound, this.reachLeftBound);
final bool reachLeftBound;
final bool reachRightBound;
final Offset position;

@override
String toString() {
return "reachLeftBound=$reachRightBound, reachRightBound=$reachLeftBound, offset=$position";
}
}

Loading

0 comments on commit 24c7214

Please sign in to comment.