列表视图构建器内的 Gridview 构建器预加载所有 gridview 项目

Gridview builder inside list view builder preloads all gridview items

我在 ListView 构建器中有一个 GridView 构建器,如下所示(完整的应用程序示例):

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(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);
  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: ListView.builder(
        itemCount: 3,
        itemBuilder: (BuildContext context, int sectionIndex) {
          return GridView.builder(
            shrinkWrap: true,
            physics: const NeverScrollableScrollPhysics(),
            padding: const EdgeInsets.only(top: 10),
            gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
              crossAxisCount: 3,
              childAspectRatio: 111 / 221,
              crossAxisSpacing: 10,
              mainAxisSpacing: 10,
            ),
            itemCount: 50,
            itemBuilder: (context, index) {
              print("Loading item $sectionIndex $index");
              return Text("Item $index");
            },
          );
        },
      ),
    );
  }
}

我在日志中得到的是 Loading item $sectionIndex $index 我当前所在部分内的所有索引。 image 但是,如果我单独使用 GridView 而不是 ListView 中的子项,它只会加载大约 10 个项目,当我向下滚动时它会加载更多(这是预期的行为)

你能告诉我在列表视图中使用网格视图我做错了什么吗?

谢谢

试试下面的代码希望对你有帮助。只需在 ListView.builder()

中添加 shrinkWrapphysics
 shrinkWrap: true,
 physics: const NeverScrollableScrollPhysics(),

完整代码:

         ListView.builder(
            itemCount: 3,
            shrinkWrap: true,
            physics: const NeverScrollableScrollPhysics(),
            itemBuilder: (BuildContext context, int sectionIndex) {
              return GridView.builder(
                shrinkWrap: true,
                physics: const NeverScrollableScrollPhysics(),
                padding: const EdgeInsets.only(top: 10),
                gridDelegate:
                    const SliverGridDelegateWithFixedCrossAxisCount(
                  crossAxisCount: 3,
                  childAspectRatio: 111 / 221,
                  crossAxisSpacing: 10,
                  mainAxisSpacing: 10,
                ),
                itemCount: 50,
                itemBuilder: (context, index) {
                  print("Loading item $sectionIndex $index");
                  return Text("Item $index");
                },
              );
            },
          ),

结果屏幕->

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);
  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  ScrollController _scrollController = ScrollController();
  late List<Widget> widgets = [_gridView(), _gridView()];
  @override
  void initState() {
    _scrollController.addListener(() {
      if (_scrollController.position.pixels ==
          _scrollController.position.maxScrollExtent) {
        setState(() {
          setState(() {
            widgets.add(_gridView());
          });
        });
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text(widget.title),
        ),
        body: ListView.builder(
          controller: _scrollController,
          shrinkWrap: true,
          padding: const EdgeInsets.only(top: 10),
          itemCount: widgets.length,
          itemBuilder: (context, index) {
            if (widgets.length - 1 == index) {
              return Center(child: Text("Load more"));
            }
            return widgets[index];
          },
        ));
  }

  Widget _gridView() {
    return GridView.builder(
      shrinkWrap: true,
      physics: const NeverScrollableScrollPhysics(),
      padding: const EdgeInsets.only(top: 10),
      gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
        crossAxisCount: 3,
        childAspectRatio: 111 / 221,
        crossAxisSpacing: 10,
        mainAxisSpacing: 10,
      ),
      itemCount: 10,
      itemBuilder: (context, index) {
        return Text("Item $index");
      },
    );
  }
}

这是因为 ListView.builder 的行为,因为 ListView.builder 是 flex widget,可以 expand 它是 scroll direction 中的 length 根据它是 children 并且遵循相同的规则是 GridView.builder。因此,当您在 ListView.builder 中调用 GridView.builder 时,GridView.builder 没有高度限制,因此它会根据可用的 space.

加载所有 child

在调用两个 GridView.builders ListView.builder 后,没有任何滚动就达到了 max length 所以 3rd GridView.builder 前两个 build.

不会同时构建

要从 GridView.builder 得到有限的结果,只需 wrapSizedBox 与特定的 height

我希望我能够向你解释。