Flutter listview moving when loading images from network

162

I wrote a function that gets a height of image in a cycle (array favorites contains Maps which contain url parameter and height parameter if loaded). The function also converts image's height in the size i actually need by formula with MediaQuery.of(context).size.width - 80 which is the width of images on screen. (Width of the screen minus 40 padding from each side).

This is the code of getting height function:

Future<void> getImageHeight(String url, index) async {
    Image image = Image.network(url);
    image.image
        .resolve(const ImageConfiguration())
        .addListener(ImageStreamListener((ImageInfo info, bool isSync) {
      favorites[index]['height'] = info.image.height *
          ((MediaQuery.of(context).size.width - 80) / info.image.width);
      setState(() {});
    }));
} 

And this is the code of image with placeholder (Container):

Container(
    color: const Color(0xffE8E6EA),
    height: favorites[index]['height'] == null || favorites[index
            ['height'].isNaN ? 0: favorites[index]['height'],
    child: Image.network(
        favorites[index]['url'],
            width: double.infinity,
    ),
),

On first loading size of placeholder is still going to be zero, because it takes time to get height of them. But after few time (it usually takes about a second or less) setState is going to be called and images will not lag on scrolling. And if you are loading your images urls from database not all at once you'll need to rerun function to get height of newly added images.

Share:
162
itsmishakiva
Author by

itsmishakiva

Updated on January 03, 2023

Comments

  • itsmishakiva
    itsmishakiva over 1 year

    i am trying to make a listview with lots of images with different dimensions loaded from network. When I scroll down everything is okay, but when i am scrolling up, first images start to load changing the position of listview. I suppose I need to have a placeholder for images with height of image, but i dont know how to get their dimensions before them loaded. Or i need smth like listview that does not move because of smth upper loading.

    • Mark
      Mark about 2 years
      Did you ever solve this? Having the same problem, and haven't been able to solve it after a few weeks now..
    • itsmishakiva
      itsmishakiva about 2 years
      Yeah, I actually did. I will post an answer today. It's a little bit tricky, and in first load image still has zero size, but after image loads for the first time, it's gonna have a placeholder, so scrolling will be okay
    • itsmishakiva
      itsmishakiva about 2 years
      Posted the answer
  • itsmishakiva
    itsmishakiva about 2 years
    Thanks for the answer! But is it possible to do smth without cropping image or adding invisible borders like sizedBox does. I mean smth like in Instagram. It seems like Instagram somehow gets dimensions of image before loading and drawing a placeholder (like Container or smth) with dimensions of image which is loading with CircularProgress in Center of it
  • Mark
    Mark almost 2 years
    Thank you for posting this! If I am understanding this solution properly, the layout will still move on the very first time an image is loaded from the network, because you do not know the size, correct?