[Solved] Flutter Pinch Zoom Image In ListView Builder

flutter pinch zoom image in flutter listview builder

In this Flutter tutorial, we’ll learn how to practically implement Flutter pinch zoom image inside list view builder. We’ll understand it using proper Flutter code example with step by step explanation.

Introduction: Flutter Pinch Zoom Image

flutter list view builder showing a list of images in which one item is pinch zoomed with clip behavior none

It means that the image will be zoomable if we pinch it. We’ll understand the below listed concepts in this tutorial:

  • We’ll make the image zoomable by pinching it.
  • We’ll create a list of images and allow the user to zoom the selected item.
  • The size of image will be set to default when the user stops pinching it. We’ll be using a simple animation for that.

Let’s now start coding this Flutter pinch zoom program.

Implementing Flutter Pinch Zoom Image Inside List View Builder (Detailed Explanation)

Below steps will guide you how to implement the feature of pinch to zoom image in Flutter list view builder.

Step 1: Create Animation, Transformation Controllers and Animation Controller

  Animation<Matrix4>? animation;
  List<AnimationController> animationControllers = [];
  List<TransformationController> controllers = [];
  • We’ve created an animation object.
  • Then we’ve created an empty list of animation controllers. Reason for creating a list of controllers is to assign each image with its own controller. Its used to animate the size of image to its default one.
  • Transformation controller is used to listen to the zoom and pan gestures.

Step 2: Ticker Provider State Mixin

class _HomePageState extends State<HomePage> with TickerProviderStateMixin{ 
  //// 
}
Use the with TickerProviderStateMixin instead of single ticker provider state mixin. Reason is that we’re working on multiple controllers.

Step 3: Function to Add Controllers To Lists

 addControllersToLists() {
    for (int i = 0; i < 10; i++) {
      controllers.add(TransformationController());
      animationControllers.add(AnimationController(
          vsync: this, duration: Duration(milliseconds: 200))
        ..addListener(() => controllers[i].value = animation!.value));
    }
  }
  1. In this function, we’ve used Flutter for loop with a range of 10.
  2. Transformation controllers will be added to its specified list.
  3. In case of animation controller:
  • First it’ll be initialized with vsync: this and duration of 200 milliseconds. The duration specifies the speed of animation.
  • Also, a listener will be added which will assign the value of animation to the transformation controllers’ values.
  • Finally, it’ll be added to the list of animation controllers.

Step 4: Calling that Function

  @override
  void initState() {
    addControllersToLists();
    super.initState();
  }
We want the function(addControllersToList()) to be called automatically when the screen loads so we’ve called it inside init state.

Step 5: Dispose The Controllers

 @override
  void dispose() {
    for (int i = 0; i < 10; i++) {
      controllers[i].dispose();
      animationControllers[i].dispose();
    }
    super.dispose();
  }
This will dispose all the controllers of list when they are no longer needed.

Step 6: Flutter List View Builder

The complete source code will be provided in the end. In here, we’ll just see the important points.

First we’ve created a list view builder which will have 10 items(images in this case). Click here to learn how to properly use Flutter image asset. See below:

flutter list view builder showing a list of images

In order to make them zoomable, we’ve to wrap it with interactive viewer. See below code:

InteractiveViewer(child:imageWidget)

flutter list view builder showing a list of images in which one item is pinch zoomed

For demonstration, we’ve pinched one image and it gets zoomed but we can see that the size remains the same. Let’s see how to make the size big.

Clip Behavior

 clipBehavior: Clip.none
flutter list view builder showing a list of images in which one item is flutter pinch zoom with clip behavior none
We have to use the clip behavior constructor of interactive viewer and set it to none. We can see in the above image that the size is now increased after the image is pinch zoomed.

Transformation Controller

Size of zoomed image will remain zoomed. In order to resize it to its default size, we’ll use two constructors of interactive viewer. Se below:

1. Transformation Controller
transformationController: controllers[index]
This is used to perform transformation on the child. Each image will have its own controller so we’ve used indexing to fetch the specified controller.

If we pinch zoom the image then it’ll remain zoomed. In order to resize it, either we’ve to manually pinch zoom out or we can specify a code that will do it automatically. In case of automation, we can use the above transformation controller.

2. On Interaction End
  onInteractionEnd: (details) {
      animation = Matrix4Tween(
        begin: controllers[index].value,
        end: Matrix4.identity()).animate(CurvedAnimation(
                 parent: animationControllers[index],
                 curve: Curves.linear));

     animationControllers[index].forward(from: 0);  // Its used to start the animation
              }

This constructor takes a function which is triggered whenever the user ends the interaction with the child(image in our case).

Inside it, we’ve specified animation from the current zoomed level to the original state. In order to make it work, we’ve to use this animation value inside our animation controller value.

For that, we’ve specified a listener to our controller which is inside init state and have assigned the animation value to the controller’s value. See below:

controllers[i].value = animation!.value  // see step 3 for complete code

Min and Max Scale

  minScale: 1
  maxScale: 4
Min scale specifies the minimum allowed scale while the max scale specifies the maximum allowed space. For demonstration, we’ve passed 4 to the max scale which will allow the image to be zoomed 4 times its original size.

These constructor takes a double(decimal) value but we can pass integer as well like shown above.

Pan Enabled

panEnabled: false
This constructor takes a Boolean(true/false) value. By default, its true. Making it false will stop the user from pan around the image to change its position when its zoomed. You can try it without specifying the transformation controller to understand it properly.

Align Pan Axis

alignPanAxis: true

By default, its false. Making it true will allow the user to pan the zoomed image only in horizontal or vertical direction, but not in the diagonal one.

So this is how we can easily implement Flutter pinch zoom image inside Flutter list view builder. If you like it then do feel free to share it with your squad of Flutter developers.

Don’t hesitate to ask if you still have any doubts related to this Flutter pinch zoom. We’ll be happy to clear all your doubts.

Click here to learn the more detailed version of pinch zoom in Flutter.

The complete source code of Flutter pinch zoom image is provided in the below block.

Flutter Pinch Zoom In List View Builder Source Code

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return MaterialApp(debugShowCheckedModeBanner: false, home: HomePage());
  }
}

class HomePage extends StatefulWidget {
  const HomePage({super.key});
  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> with TickerProviderStateMixin {

  Animation<Matrix4>? animation;
  List<AnimationController> animationControllers = [];
  List<TransformationController> controllers = [];

  addControllersToLists() {
    for (int i = 0; i < 10; i++) {
      controllers.add(TransformationController());
      animationControllers.add(AnimationController(
          vsync: this, duration: Duration(milliseconds: 200))
        ..addListener(() => controllers[i].value = animation!.value));
    }
  }

  @override
  void initState() {
    addControllersToLists();
    super.initState();
  } 

  @override 
  void dispose() 
   { 
     for (int i = 0; i < 10; i++) { 
       controllers[i].dispose(); 
       animationControllers[i].dispose();
         } 
     super.dispose();
    }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: ListView.builder(
          itemCount: 10,
          itemBuilder: (context, index) {

            return InteractiveViewer(
              alignPanAxis: true,
              panEnabled: false,
              clipBehavior: Clip.none,
              transformationController: controllers[index],
              minScale: 1,
              maxScale: 4,

              onInteractionEnd: (details) {
                animation = Matrix4Tween(
                        begin: controllers[index].value,
                        end: Matrix4.identity())
                    .animate(CurvedAnimation(
                        parent: animationControllers[index],
                        curve: Curves.linear));
                animationControllers[index].forward(from: 0);
              },

              child: Padding(
                padding: EdgeInsets.all(30),
                child: Image.asset(
                  'assets/cat.jpg',
                  height: 200,
                  width: double.infinity,
                  fit: BoxFit.cover,
                ),
              ),
            );
          }),
    );
  }
}

Conclusion

In conclusion, hope you now have grasp a detailed knowledge of how to use Flutter pinch zoom inside Flutter list view builder. Do feel free to leave your valuable thoughts in the comment section.

We’d be super delighted to see you visit our other tutorials on Flutter app development. Thank you for reading this one.

Leave a Comment

Your email address will not be published. Required fields are marked *