Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Popup photo view #167

Closed
anderscheow opened this issue Aug 5, 2019 · 18 comments
Closed

Popup photo view #167

anderscheow opened this issue Aug 5, 2019 · 18 comments
Labels
enhancement New feature or request

Comments

@anderscheow
Copy link

Is your feature request related to a problem? Please describe.
It is quite troublesome to implement a popup photo view with zoom, drag and also drag to dismiss (change in transparency), since this library already provided the foundation of zoomable image, it is great that the library able to extend to a popup version.

Describe the solution you'd like
A popup photo view which able to zoom, drag and also drag to dismiss (change in transparency) similar to Facebook.

@renancaraujo renancaraujo added the enhancement New feature or request label Aug 5, 2019
@renancaraujo
Copy link
Member

Since there is a lot of people feeling the need for this feature (myself included on one of my apps), I think it is valid to relive the discussion.

Problem:
PhotoView is a widget that does not have a "dismissable" behavior. It only takes care of dealing with receiving gestures in order to scale and translate(move) an image and takes care to render the image(or custom child) correctly. due to its simplicity, there are several use cases of PhotoView and this package is one of the most downloaded on PUB. We have to make sure that any feature won't break other use cases.

TBH I don't think a dismissable PhotoView is in the "scope" of this widget, BUT this doesn't mean we won't do anything about that.

  • We can create an example on the app in order to show a sample of code and who knows another package?
  • We can create a "wrapper" widget with the popup behavior and publish on pub as a separate package.

@anderscheow
Copy link
Author

There's a similar package which able to do the popup thing extended_image, it is great if this package able to achieve that.

@devxpy
Copy link

devxpy commented Nov 9, 2019

I think this can be solved if we somehow remove the background.

showDialog(
  context: context,
  builder: (context) {
    return PhotoView(
      imageProvider: ...,
      backgroundDecoration: BoxDecoration(
        shape: BoxShape.circle,
        color: Colors.black,
      ),
    );
  },
);

Clicking outside the black circle dismisses the photoview. So if just remove the background...

@renancaraujo
Copy link
Member

@devxpy You can wrap photoview on a container or sizedbox with the same size as the image.

@devxpy
Copy link

devxpy commented Nov 11, 2019

@renancaraujo Thanks for replying!

I tried that but it doesn't quite work. Here are few observations -

  1. It doesn't work at all unless widgets are wrapped inside a Dialog.

So this:

SizedBox(
  width: 3000 / 10,
  height: 2002 / 10,
  child: PhotoView(
    imageProvider: imageProvider,
  ),
);

produces:


  1. When wrapped inside a Dialog, this breaks zoom/pan outside of the SizedBox.

This:

Dialog(
  child: SizedBox(
    width: 3000 / 10,
    height: 2002 / 10,
    child: PhotoView(
      imageProvider: imageProvider,
    ),
  ),
);

Produces:

But it won't allow any interaction with a zoomed image beyond the constraints of the sized box.


  1. If you zoom out, the sized box is visible again.

@devxpy
Copy link

devxpy commented Nov 11, 2019

Update: Edited the source code for the plugin, to remove the Container, and it totally fixes this!

$ git diff
diff --git a/lib/src/core/photo_view_core.dart b/lib/src/core/photo_view_core.dart
index 6d1f462..7868640 100644
--- a/lib/src/core/photo_view_core.dart
+++ b/lib/src/core/photo_view_core.dart
@@ -279,18 +279,12 @@ class PhotoViewCoreState extends State<PhotoViewCore>
               child: _buildHero(),
             );
             return PhotoViewGestureDetector(
-              child: Container(
-                child: Center(
-                  child: Transform(
-                    child: customChildLayout,
-                    transform: matrix,
-                    alignment: basePosition,
-                  ),
+              child: Center(
+                child: Transform(
+                  child: customChildLayout,
+                  transform: matrix,
+                  alignment: basePosition,
                 ),
-                decoration: widget.backgroundDecoration ??
-                    const BoxDecoration(
-                      color: const Color.fromRGBO(0, 0, 0, 1.0),
-                    ),
               ),
               onDoubleTap: nextScaleState,
               onScaleStart: onScaleStart,

out

@renancaraujo, Can I submit a PR? Can make a switch called enableBg that optionally removes this Container.

@Zeeshan0201
Copy link

@renancaraujo yes we need a solution for exit photo_view and back to the previous screen.

@Zeeshan0201
Copy link

@devxpy Great! It's same feature which we need to implement...

@renancaraujo
Copy link
Member

@devxpy Absolutely, feel free to open the PR

@Zeeshan0201
Copy link

Zeeshan0201 commented Nov 14, 2019

@devxpy please let us know whenever your PR submitted and this upgraded to latest packages code, thanks.

@renancaraujo
Copy link
Member

Hello folks, just added some example regarding both usages in a dialog and a drag to dismiss.
Check the example App!

Options that allow this behavior were added on 0.9.0.

To use in a Dialog, set tightMode: true

dialog

To add drag to bottom dismiss, combine PhotoView with showBottomSheet or Dismissible

dragbottom

@Zeeshan0201
Copy link

@renancaraujo thanks for adding !

@betorcs
Copy link

betorcs commented Aug 25, 2022

@renancaraujo does it possible have the same behavior as you shown using Dialog with PhotoViewGallery? I did some tries, but I failed.

@renancaraujo
Copy link
Member

@renancaraujo does it possible have the same behavior as you shown using Dialog with PhotoViewGallery? I did some tries, but I failed.

That demo should be available in the example app, did you try to run it?

If following the example app doesn't work, would you ping on discord? Thanks.

@betorcs
Copy link

betorcs commented Aug 25, 2022

@renancaraujo first of all, thanks for quick reply.

I suppose you're talking about this example, right? It's using PhotoView as child, in my case I'm using PhotoViewGallery and it doesn't work.

Yeah I can ping you on discord. thx

@giovanigm
Copy link

Hello! I'm having the exact same problem as @betorcs.

@betorcs, if you manage to solve it, can you please share the solution in this thread?

@giovanigm
Copy link

Hello again!

@betorcs I've solved it!

This is the code:

showGeneralDialog(
  context: context,
  barrierColor: Colors.transparent,
  transitionDuration: const Duration(milliseconds: 200),
  pageBuilder: (_, __, ___) {
    return MediaPage(urls: urls);
  },
);

class MediaPage extends StatefulWidget {
  final List<String> urls;

  const MediaPage({
    Key? key,
    required this.urls,
  }) : super(key: key);

  @override
  State<MediaPage> createState() => _MediaPageState();
}

class _MediaPageState extends State<MediaPage> with TickerProviderStateMixin {
  late AnimationController _fadeController;

  @override
  void initState() {
    _fadeController = AnimationController(vsync: this);
    super.initState();
  }

  @override
  void dispose() {
    _fadeController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return AnimatedBuilder(
      animation: _fadeController,
      builder: (context, child) => Container(
        color: HoundPalette.background.withOpacity(1 - _fadeController.value),
        child: child,
      ),
      child: PhotoViewGallery.builder(
        scrollPhysics: const BouncingScrollPhysics(),
        backgroundDecoration: const BoxDecoration(color: Colors.transparent),
        itemCount: widget.urls.length,
        builder: (BuildContext context, int index) {
          final url = widget.urls[index];

          return PhotoViewGalleryPageOptions.customChild(
            child: Dismissible(
              key: Key(url),
              direction: DismissDirection.vertical,
              onUpdate: (details) {
                _fadeController.value = details.progress;
              },
              resizeDuration: const Duration(milliseconds: 10), // reduces the time to call 'onDismissed'
              onDismissed: (direction) {
                Navigator.pop(context);
              },
              child: PhotoView(
                imageProvider: NetworkImage(url),
                tightMode: true,
                minScale: PhotoViewComputedScale.contained,
                initialScale: PhotoViewComputedScale.contained,
                backgroundDecoration:
                    const BoxDecoration(color: Colors.transparent),
              ),
            ),
          );
        },
      ),
    );
  }
}

@betorcs
Copy link

betorcs commented Sep 22, 2022

@giovanigm thank you for you reply and sorry to answer only now, I was on vacation.

I just tried your sample, it works almost the same using showBottomSheet.

The behavior I'd need it's to close it on tap in background

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

6 participants