仅在视口内加载图像

问题描述 投票:0回答:1

我有一个带有ListView的脚手架,它是一个能够滚动的孩子。在它的顶部有一个标题容器,以及一列包含图像列表的列。

我只希望在图像出现在视口中但所有图像都同时开始加载时才加载它们。

当我将这些图像添加到ListView的子级时,不会发生这种情况,但是我想将它们放在单独的小部件中,以保持代码的清洁。有可能吗?

这里是一个简化的示例:

const List<String> images = [
  'https://cataas.com/cat?hash=1',
  'https://cataas.com/cat?hash=2',
  'https://cataas.com/cat?hash=3',
  'https://cataas.com/cat?hash=4',
  'https://cataas.com/cat?hash=5',
  'https://cataas.com/cat?hash=6',
  'https://cataas.com/cat?hash=7',
  'https://cataas.com/cat?hash=8',
];

// Scaffold child
class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ListView(
      children: [
        // Header
        Placeholder(
          fallbackHeight: 300,
        ),
        Category(),
        SizedBox(height: 16),
        Category(),
      ],
    );
  }
}

class Category extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    print('Build category');
    return Column(
      children: [
        Padding(
          padding: EdgeInsets.all(32),
          child: Text('CATEGORY TITLE'),
        ),
        ...images.map((image) => CategoryItem(image)),
      ],
    );
  }
}

class CategoryItem extends StatelessWidget {
  final String imageUrl;

  CategoryItem(this.imageUrl);

  @override
  Widget build(BuildContext context) {
    print('Build image: $imageUrl');
    return FadeInImage.memoryNetwork(
      fit: BoxFit.cover,
      placeholder: kTransparentImage,
      image: imageUrl,
    );
  }
}
flutter dart lazy-loading
1个回答
0
投票

您需要使用ListView.builder,因为它会延迟呈现其子级。另外,您还需要使用一个列表。

问题是,在加载图像之前您不知道图像的大小,因此所有高度为0的图像都将立即生成。但是,如果将它们设置为固定高度,它将按预期工作。

1

class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final children = [
      // Header
      Placeholder(
        fallbackHeight: 300,
      ),
      Padding(
        padding: EdgeInsets.all(32),
        child: Text('CATEGORY TITLE'),
      ),
      ...images.map((image) => CategoryItem(image)),
      SizedBox(height: 16),
      Padding(
        padding: EdgeInsets.all(32),
        child: Text('CATEGORY TITLE'),
      ),
      ...images.map((image) => CategoryItem(image)),
    ];

    return Scaffold(
      body: ListView.builder(
        itemCount: children.length,
        itemBuilder: (context, i) => children[i],
      )
    );
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.