skip to Main Content

Thank you for taking the time to read this. I’m having an issue with the PhotoView in flutter. Basically, I’ve integrated a carousel which shows all the images I have associated to an exercise. These images are imgur images which I show with the link.

This works well, the carousel shows all images I’ve asociated with the exercise through the database (I am not using API, rather, direct database queries) and when I tap the image (onTap) it displays a PhotoView, which allows the user to see the dedicated image, zoom in, etc. Very useful.

The one issue I have is that the onTap will always get the same image. As in, if I have 3 images in positions 0,1,2 ; If I press image two, it will show me the PhotoView of image 0. If I press image 3, same thing.

In the photo view I can swipe to see the next or previous image, so it’s loading them correctly, It’s just this minimal error.

I’d like to clarify that I’m no expert in flutter or front-end in general, so there may be a few mistakes (and code may be a bit messier then should be), thank you for bearing with me.

(Btw, I’ve uploaded a screen recording of this to imgur, here: Imgur Link )

Here’s the relevant code fragment:

body: FutureBuilder<List<Exercise>>(
                  future: fetchExercisesForRoutine(routine.id),
                  builder: (context, snapshot) {
                    if (snapshot.connectionState == ConnectionState.waiting) {
                      return CircularProgressIndicator();
                    } else if (snapshot.hasError) {
                      return Text('Error fetching exercises: ${snapshot.error}');
                    } else {
                      final exercises = snapshot.data ?? [];
                      return ListView.builder(
                        shrinkWrap: true,
                        itemCount: exercises.length,
                        itemBuilder: (context, index) {
                          final exercise = exercises[index];
                          return Center(
                            child: Card(
                              child: Column(
                                children: [
                                  Text(exercise.name),
                                  Text(exercise.description),
                                  Text('Time: ${exercise.time}'),
                                  GestureDetector(
                                    onTap: () {
                                      final screenWidth = MediaQuery.of(context).size.width;
                                      final screenHeight = MediaQuery.of(context).size.height;
                                      final squareSize = screenWidth < screenHeight ? screenWidth : screenHeight;
                                      showDialog(
                                        context: context,
                                        builder: (BuildContext context) {
                                          return Dialog(
                                            backgroundColor: Colors.transparent,
                                            child: Container(
                                              color: Colors.transparent,
                                              constraints: BoxConstraints.expand(
                                                height: squareSize,
                                                width: squareSize,
                                              ),
                                              child: PageView.builder(
                                                itemCount: exercise.imageLinks.length,
                                                itemBuilder: (context, index) {
                                                  return PhotoView(
                                                    imageProvider: NetworkImage(exercise.imageLinks[index]),
                                                    backgroundDecoration: BoxDecoration(
                                                      color: Colors.transparent,
                                                    ),
                                                    minScale: PhotoViewComputedScale.contained * 0.8,
                                                    maxScale: PhotoViewComputedScale.covered * 2.0,
                                                  );
                                                },
                                              ),
                                            ),
                                          );
                                        },
                                      );
                                    },
                                    child: CarouselSlider.builder(
                                      options: CarouselOptions(
                                        viewportFraction: 0.65,
                                        aspectRatio: 4 / 3,
                                        enlargeCenterPage: true,
                                      ),
                                      itemCount: exercise.imageLinks.length,
                                      itemBuilder: (context, imageIndex, ___) {
                                        final imageLink = exercise.imageLinks[imageIndex];
                                        return CachedNetworkImage(
                                          imageUrl: imageLink, // Use the image link from the list
                                          placeholder: (context, url) => CircularProgressIndicator(),
                                          errorWidget: (context, url, error) => Icon(Icons.error),
                                          fit: BoxFit.cover,
                                        );
                                      },
                                    ),
                                  ),
                                ],
                              ),
                            ),
                          );
                        },
                      );
                    }
                  },
                ),

Thank you so much for any help!

I expect the error to be not definining an index in the onTap, but I can’t quite pinpoint how to do it.

I’ve looked at a few tutorials and went correcting it along the way to get where I am now, where everything works just this minor inconvenience.

Imgur Link to how it’s looking

2

Answers


  1. Chosen as BEST ANSWER

    As Ildeberto responded, the error was that the onTap was from the carousel, not the photoView. If anyone is interested in the full code (provided by Ildeberto and I modified a small bit that was redundant in my case), I'll leave it down below.

    Thank you!

    body: FutureBuilder<List<Exercise>>(
          future: fetchExercisesForRoutine(routine.id),
          builder: (context, snapshot) {
    
    if (snapshot.connectionState == ConnectionState.waiting) {
    return Center(child: CircularProgressIndicator());
    } else if (snapshot.hasError) {
    return Text('Error fetching exercises: ${snapshot.error}');
    } else {
      final exercises = snapshot.data ?? [];
      return ListView.builder(
        shrinkWrap: true,
        itemCount: exercises.length,
        itemBuilder: (context, index) {
          final exercise = exercises[index];
          return Center(
            child: Card(
              child: Column(
                children: [
                  Text(exercise.name),
                  Text(exercise.description),
                  Text('Time: ${exercise.name}'),
                  CarouselSlider.builder(
                    options: CarouselOptions(
                      viewportFraction: 0.65,
                      aspectRatio: 4 / 3,
                      enlargeCenterPage: true,
                    ),
                    itemCount: exercise.imageLinks.length,
                    itemBuilder: (context, imageIndex, ___) {
                      final imageLink = exercise.imageLinks[imageIndex];
                      return GestureDetector(
                          onTap: () {
                            final screenWidth =
                                MediaQuery
                                    .of(context)
                                    .size
                                    .width;
                            final screenHeight =
                                MediaQuery
                                    .of(context)
                                    .size
                                    .height;
                            final squareSize = screenWidth < screenHeight
                                ? screenWidth
                                : screenHeight;
                            showDialog(
                                context: context,
                                builder: (BuildContext context) {
                                  return Dialog(
                                    backgroundColor: Colors.transparent,
                                    child: Container(
                                      color: Colors.transparent,
                                      constraints: BoxConstraints.expand(
                                        height: squareSize,
                                        width: squareSize,
                                      ),
                                      child: PageView(
                                        children: [
                                      PhotoView(
                                      imageProvider: NetworkImage(exercise.imageLinks[imageIndex]),
                                      backgroundDecoration: BoxDecoration(
                                        color: Colors.transparent,
                                      ),
                                      minScale: PhotoViewComputedScale.contained * 0.8,
                                      maxScale: PhotoViewComputedScale.covered * 2.0,),
                                        ],
                                      ),
                                    ),
                                  );
                                });
                          },
                          child: CachedNetworkImage(
                            imageUrl: imageLink, // Use the image link from the list
                            placeholder: (context, url) => CircularProgressIndicator(),
                            errorWidget: (context, url, error) => Icon(Icons.error),
                            fit: BoxFit.cover,
                          ));
                    },
                  ),
                ],
              ),
            ),
          );
        },
      );
    }}),
    

  2. Your code is getting the Touch from the Full Carousel ,don’t from the single Foto that you are clicking,

    take a look in this code,

       body: FutureBuilder<List<Exercise>>(
          future: fetchExercisesForRoutine(routine.id),
          builder: (context, snapshot) {
    
    if (snapshot.connectionState == ConnectionState.waiting) {
    return Center(child: CircularProgressIndicator());
    } else if (snapshot.hasError) {
    return Text('Error fetching exercises: ${snapshot.error}');
    } else {
      final exercises = snapshot.data ?? [];
      return ListView.builder(
        shrinkWrap: true,
        itemCount: exercises.length,
        itemBuilder: (context, index) {
          final exercise = exercises[index];
          return Center(
            child: Card(
              child: Column(
                children: [
                  Text(exercise.name),
                  Text(exercise.description),
                  Text('Time: ${exercise.name}'),
                  CarouselSlider.builder(
                    options: CarouselOptions(
                      viewportFraction: 0.65,
                      aspectRatio: 4 / 3,
                      enlargeCenterPage: true,
                    ),
                    itemCount: exercises.skip(index).length,
                    itemBuilder: (context, imageIndex, ___) {
                      final imageLink = exercise.imageLinks[imageIndex];
                      return GestureDetector(
                          onTap: () {
                            final screenWidth =
                                MediaQuery
                                    .of(context)
                                    .size
                                    .width;
                            final screenHeight =
                                MediaQuery
                                    .of(context)
                                    .size
                                    .height;
                            final squareSize = screenWidth < screenHeight
                                ? screenWidth
                                : screenHeight;
                            showDialog(
                                context: context,
                                builder: (BuildContext context) {
                                  return Dialog(
                                    backgroundColor: Colors.transparent,
                                    child: Container(
                                      color: Colors.transparent,
                                      constraints: BoxConstraints.expand(
                                        height: squareSize,
                                        width: squareSize,
                                      ),
                                      child: PageView(
    
                                        children: [
                                      PhotoView(
                                      imageProvider: NetworkImage(exercise.imageLinks[imageIndex]),
                                      backgroundDecoration: BoxDecoration(
                                        color: Colors.transparent,
                                      ),
                                      minScale: PhotoViewComputedScale.contained * 0.8,
                                      maxScale: PhotoViewComputedScale.covered * 2.0,
    
    
                                          ),
                                          for(Exercise exercise in exercises.skip(imageIndex))
                                            PhotoView(
                                              imageProvider: NetworkImage(imageLink),
                                              backgroundDecoration:  BoxDecoration(
                                                color: Colors.transparent,
                                              ),
                                              minScale: PhotoViewComputedScale.contained * 0.8,
                                              maxScale: PhotoViewComputedScale.covered * 2.0,
    
    
                                            ),
                                        ],
                                      ),
                                    ),
                                  );
                                });
                          },
                          child: CachedNetworkImage(
                            imageUrl: imageLink, // Use the image link from the list
                            placeholder: (context, url) => CircularProgressIndicator(),
                            errorWidget: (context, url, error) => Icon(Icons.error),
                            fit: BoxFit.cover,
                          ));
                    },
                  ),
                ],
              ),
            ),
          );
        },
      );
    }}),
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search