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),
 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),
 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 imageProvider, LoadingBuilder loadingBuilder, Widget loadFailedChild, Decoration backgroundDecoration, 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, Size customSize, HitTestBehavior gestureDetectorBehavior, bool tightMode, FilterQuality filterQuality, bool disableGestures, ImageErrorWidgetBuilder errorBuilder})
Creates a widget that displays a zoomable image. [...]
PhotoView.customChild({Key key, @required Widget child, Size childSize, Decoration backgroundDecoration, 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, Size customSize, HitTestBehavior gestureDetectorBehavior, bool tightMode, FilterQuality filterQuality, bool disableGestures})
Creates a widget that displays a zoomable child. [...]

Properties

backgroundDecoration Decoration
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
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. [...]
@nonVirtual, read-only, inherited
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
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. [...]
final, inherited
loadFailedChild Widget
Show loadFailedChild when the image failed to load
@Deprecated("Use errorBuilder instead"), final
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
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.
read-only, inherited
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
tightMode bool
Enables tight mode, making background container assume the size of the image/child. Useful when inside a Dialog
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. [...]
@protected, inherited
debugFillProperties(DiagnosticPropertiesBuilder properties) → void
Add additional properties associated with the node. [...]
inherited
noSuchMethod(Invocation invocation) → dynamic
Invoked when a non-existent 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
Returns 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. [...]
@nonVirtual, inherited