PhotoView class

A StatefulWidget that contains all the photo view rendering elements.

Sample code to use within an image:

PhotoView(
 imageProvider: imageProvider,
 loadingBuilder: (context, progress) => Center(
           child: Container(
             width: 20.0,
             height: 20.0,
             child: CircularProgressIndicator(
               value: _progress == null
                   ? null
                   : _progress.cumulativeBytesLoaded /
                       _progress.expectedTotalBytes,
             ),
           ),
         ),
 backgroundDecoration: BoxDecoration(color: Colors.black),
 semanticLabel: 'Some label',
 gaplessPlayback: false,
 customSize: MediaQuery.of(context).size,
 heroAttributes: const HeroAttributes(
  tag: "someTag",
  transitionOnUserGestures: true,
 ),
 scaleStateChangedCallback: this.onScaleStateChanged,
 enableRotation: true,
 controller:  controller,
 minScale: PhotoViewComputedScale.contained * 0.8,
 maxScale: PhotoViewComputedScale.covered * 1.8,
 initialScale: PhotoViewComputedScale.contained,
 basePosition: Alignment.center,
 scaleStateCycle: scaleStateCycle
);

You can customize to show an custom child instead of an image:

PhotoView.customChild(
 child: Container(
   width: 220.0,
   height: 250.0,
   child: const Text(
     "Hello there, this is a text",
   )
 ),
 childSize: const Size(220.0, 250.0),
 backgroundDecoration: BoxDecoration(color: Colors.black),
 semanticLabel: 'Some label',
 gaplessPlayback: false,
 customSize: MediaQuery.of(context).size,
 heroAttributes: const HeroAttributes(
  tag: "someTag",
  transitionOnUserGestures: true,
 ),
 scaleStateChangedCallback: this.onScaleStateChanged,
 enableRotation: true,
 controller:  controller,
 minScale: PhotoViewComputedScale.contained * 0.8,
 maxScale: PhotoViewComputedScale.covered * 1.8,
 initialScale: PhotoViewComputedScale.contained,
 basePosition: Alignment.center,
 scaleStateCycle: scaleStateCycle
);

The maxScale, minScale and initialScale options may be double or a PhotoViewComputedScale constant

Sample using maxScale, minScale and initialScale

PhotoView(
 imageProvider: imageProvider,
 minScale: PhotoViewComputedScale.contained * 0.8,
 maxScale: PhotoViewComputedScale.covered * 1.8,
 initialScale: PhotoViewComputedScale.contained * 1.1,
);

customSize is used to define the viewPort size in which the image will be scaled to. This argument is rarely used. By default is the size that this widget assumes.

The argument gaplessPlayback is used to continue showing the old image (true), or briefly show nothing (false), when the imageProvider changes.By default it's set to false.

To use within an hero animation, specify heroAttributes. When heroAttributes is specified, the image provider retrieval process should be sync.

Sample using hero animation:

// screen1
  ...
  Hero(
    tag: "someTag",
    child: Image.asset(
      "assets/large-image.jpg",
      width: 150.0
    ),
  )
// screen2
...
child: PhotoView(
  imageProvider: AssetImage("assets/large-image.jpg"),
  heroAttributes: const HeroAttributes(tag: "someTag"),
)

Note: If you don't want to the zoomed image do not overlaps the size of the container, use ClipRect

Controllers

Controllers, when specified to PhotoView widget, enables the author(you) to listen for state updates through a Stream and change those values externally.

While PhotoViewScaleStateController is only responsible for the scaleState, PhotoViewController is responsible for all fields os PhotoViewControllerValue.

To use them, pass a instance of those items on controller or scaleStateController;

Since those follows the standard controller pattern found in widgets like PageView and ScrollView, whoever instantiates it, should dispose it afterwards.

Example of controller usage, only listening for state changes:

class _ExampleWidgetState extends State<ExampleWidget> {

  PhotoViewController controller;
  double scaleCopy;

  @override
  void initState() {
    super.initState();
    controller = PhotoViewController()
      ..outputStateStream.listen(listener);
  }

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

  void listener(PhotoViewControllerValue value){
    setState((){
      scaleCopy = value.scale;
    })
  }

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: <Widget>[
        Positioned.fill(
            child: PhotoView(
              imageProvider: AssetImage("assets/pudim.png"),
              controller: controller,
            );
        ),
        Text("Scale applied: $scaleCopy")
      ],
    );
  }
}

An example of scaleStateController with state changes:

class _ExampleWidgetState extends State<ExampleWidget> {

  PhotoViewScaleStateController scaleStateController;

  @override
  void initState() {
    super.initState();
    scaleStateController = PhotoViewScaleStateController();
  }

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

  void goBack(){
    scaleStateController.scaleState = PhotoViewScaleState.originalSize;
  }

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: <Widget>[
        Positioned.fill(
            child: PhotoView(
              imageProvider: AssetImage("assets/pudim.png"),
              scaleStateController: scaleStateController,
            );
        ),
        FlatButton(
          child: Text("Go to original size"),
          onPressed: goBack,
        );
      ],
    );
  }
}
Inheritance

Constructors

PhotoView({Key? key, required ImageProvider<Object>? imageProvider, LoadingBuilder? loadingBuilder, BoxDecoration? backgroundDecoration, bool wantKeepAlive = false, String? semanticLabel, bool gaplessPlayback = false, PhotoViewHeroAttributes? heroAttributes, ValueChanged<PhotoViewScaleState>? scaleStateChangedCallback, bool enableRotation = false, PhotoViewControllerBase<PhotoViewControllerValue>? controller, PhotoViewScaleStateController? scaleStateController, dynamic maxScale, dynamic minScale, dynamic initialScale, Alignment? basePosition, ScaleStateCycle? scaleStateCycle, PhotoViewImageTapUpCallback? onTapUp, PhotoViewImageTapDownCallback? onTapDown, PhotoViewImageScaleEndCallback? onScaleEnd, Size? customSize, HitTestBehavior? gestureDetectorBehavior, bool? tightMode, FilterQuality? filterQuality, bool? disableGestures, ImageErrorWidgetBuilder? errorBuilder, bool? enablePanAlways, bool? strictScale})
Creates a widget that displays a zoomable image.
PhotoView.customChild({Key? key, required Widget? child, Size? childSize, BoxDecoration? backgroundDecoration, bool wantKeepAlive = false, PhotoViewHeroAttributes? heroAttributes, ValueChanged<PhotoViewScaleState>? scaleStateChangedCallback, bool enableRotation = false, PhotoViewControllerBase<PhotoViewControllerValue>? controller, PhotoViewScaleStateController? scaleStateController, dynamic maxScale, dynamic minScale, dynamic initialScale, Alignment? basePosition, ScaleStateCycle? scaleStateCycle, PhotoViewImageTapUpCallback? onTapUp, PhotoViewImageTapDownCallback? onTapDown, PhotoViewImageScaleEndCallback? onScaleEnd, Size? customSize, HitTestBehavior? gestureDetectorBehavior, bool? tightMode, FilterQuality? filterQuality, bool? disableGestures, bool? enablePanAlways, bool? strictScale})
Creates a widget that displays a zoomable child.

Properties

backgroundDecoration BoxDecoration?
Changes the background behind image, defaults to Colors.black.
final
basePosition Alignment?
The alignment of the scale origin in relation to the widget size. Default is Alignment.center
final
child Widget?
The specified custom child to be shown instead of a image
final
childSize Size?
The size of the custom child. PhotoView uses this value to compute the relation between the child and the container's size to calculate the scale value.
final
controller PhotoViewControllerBase<PhotoViewControllerValue>?
A way to control PhotoView transformation factors externally and listen to its updates
final
customSize Size?
Defines the size of the scaling base of the image inside PhotoView, by default it is MediaQuery.of(context).size.
final
disableGestures bool?
final
enablePanAlways bool?
Enable pan the widget even if it's smaller than the hole parent widget. Useful when you want to drag a widget without restrictions.
final
enableRotation bool
A flag that enables the rotation gesture support
final
errorBuilder ImageErrorWidgetBuilder?
Show loadFailedChild when the image failed to load
final
filterQuality FilterQuality?
Quality levels for image filters.
final
gaplessPlayback bool
This is used to continue showing the old image (true), or briefly show nothing (false), when the imageProvider changes. By default it's set to false.
final
gestureDetectorBehavior HitTestBehavior?
HitTestBehavior to be passed to the internal gesture detector.
final
hashCode int
The hash code for this object.
no setterinherited
heroAttributes PhotoViewHeroAttributes?
Attributes that are going to be passed to PhotoViewCore's Hero. Leave this property undefined if you don't want a hero animation.
final
imageProvider ImageProvider<Object>?
Given a imageProvider it resolves into an zoomable image widget using. It is required
final
initialScale → dynamic
Defines the initial size in which the image will be assume in the mounting of the component, it is proportional to the original image size. Can be either a double (absolute value) or a PhotoViewComputedScale, that can be multiplied by a double
final
key Key?
Controls how one widget replaces another widget in the tree.
finalinherited
loadingBuilder LoadingBuilder?
While imageProvider is not resolved, loadingBuilder is called by PhotoView into the screen, by default it is a centered CircularProgressIndicator
final
maxScale → dynamic
Defines the maximum size in which the image will be allowed to assume, it is proportional to the original image size. Can be either a double (absolute value) or a PhotoViewComputedScale, that can be multiplied by a double
final
minScale → dynamic
Defines the minimum size in which the image will be allowed to assume, it is proportional to the original image size. Can be either a double (absolute value) or a PhotoViewComputedScale, that can be multiplied by a double
final
onScaleEnd PhotoViewImageScaleEndCallback?
A pointer that will trigger a scale has stopped contacting the screen at a particular location.
final
onTapDown PhotoViewImageTapDownCallback?
A pointer that might cause a tap has contacted the screen at a particular location.
final
onTapUp PhotoViewImageTapUpCallback?
A pointer that will trigger a tap has stopped contacting the screen at a particular location.
final
runtimeType Type
A representation of the runtime type of the object.
no setterinherited
scaleStateChangedCallback ValueChanged<PhotoViewScaleState>?
A Function to be called whenever the scaleState changes, this happens when the user double taps the content ou start to pinch-in.
final
scaleStateController PhotoViewScaleStateController?
A way to control PhotoViewScaleState value externally and listen to its updates
final
scaleStateCycle ScaleStateCycle?
Defines de next PhotoViewScaleState given the actual one. Default is defaultScaleStateCycle
final
semanticLabel String?
A Semantic description of the image.
final
strictScale bool?
Enable strictScale will restrict user scale gesture to the maxScale and minScale values.
final
tightMode bool?
Enables tight mode, making background container assume the size of the image/child. Useful when inside a Dialog
final
wantKeepAlive bool
This is used to keep the state of an image in the gallery (e.g. scale state). false -> resets the state (default) true -> keeps the state
final

Methods

createElement() StatefulElement
Creates a StatefulElement to manage this widget's location in the tree.
inherited
createState() State<StatefulWidget>
Creates the mutable state for this widget at a given location in the tree.
override
debugDescribeChildren() List<DiagnosticsNode>
Returns a list of DiagnosticsNode objects describing this node's children.
inherited
debugFillProperties(DiagnosticPropertiesBuilder properties) → void
Add additional properties associated with the node.
inherited
noSuchMethod(Invocation invocation) → dynamic
Invoked when a nonexistent method or property is accessed.
inherited
toDiagnosticsNode({String? name, DiagnosticsTreeStyle? style}) DiagnosticsNode
Returns a debug representation of the object that is used by debugging tools and by DiagnosticsNode.toStringDeep.
inherited
toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) String
A string representation of this object.
inherited
toStringDeep({String prefixLineOne = '', String? prefixOtherLines, DiagnosticLevel minLevel = DiagnosticLevel.debug}) String
Returns a string representation of this node and its descendants.
inherited
toStringShallow({String joiner = ', ', DiagnosticLevel minLevel = DiagnosticLevel.debug}) String
Returns a one-line detailed description of the object.
inherited
toStringShort() String
A short, textual description of this widget.
inherited

Operators

operator ==(Object other) bool
The equality operator.
inherited