美文网首页
Flutter 组件之 ListView、GridView

Flutter 组件之 ListView、GridView

作者: Abner_XuanYuan | 来源:发表于2023-10-10 16:26 被阅读0次

    1、ListView

    列表分类:垂直列表、垂直图文列表、水平列表、动态列表。

    1、列表常用参数
    ListView({
      Key key,
      //Axis类型可选命名参数,设置沿横轴还是纵轴滚动
      Axis scrollDirection = Axis.vertical,
      //bool类型可选命名参数,用于设置视图的滚动方向是否为读取方向
      bool reverse = false,
      //ScrollController类型可选命名参数,控制滚动视图滚动位置的控制器
      ScrollController controller,
      //bool类型可选命名参数,是否是与父PrimaryScrollController相关联的主滚动视图
      bool primary,
      //ScrollPhysics类型可选命名参数,滚动视图应如何响应用户输入
      ScrollPhysics physics,
      //boo类型可选命名参数,crollDirection中滚动视图的范围是否应由正在查看的内容确定
      bool shrinkWrap = false,
      //EdgeInsetsGeometry类型可选命名参数,内边距,使用EdgeInsets
      EdgeInsetsGeometry padding,
      //double类型可选命名参数,不为空则强制子级在滚动方向上具有给定范围
      this.itemExtent,
      //bool类型可选命名参数,是否将每个子Widget都包装在AutomaticKeepAlive组件中
      bool addAutomaticKeepAlives = true,
      //bool类型可选命名参数,是否将每个子Widget都包装在RepaintBoundary组件中
      bool addRepaintBoundaries = true,
      //bool类型可选命名参数,是否将每个子Widget都包装在IndexedSemantics组件中
      bool addSemanticIndexes = true,
      //double类型可选命名参数,用于设置不可见的缓存区域的大小
      double cacheExtent,
      //List<Widget>类型可选命名参数,用于设置滚动列表的每一项Widget
      List<Widget> children = const <Widget>[],
      //int类型可选命名参数,为ListView中的子列表中Widget提供语义信息的数量
      int semanticChildCount,
      //DragStartBehavior类型可选命名参数,确定处理拖动开始行为的方式
      DragStartBehavior dragStartBehavior = DragStartBehavior.start,
    })
    
    //此构造方法采用 IndexedWidgetBuilder,可以根据需要创建子 Widget。适用于有大量或无限个子Widget的ListView。其只对可见的子 Widget 进行构建  
    ListView.builder({
      Key key,
      //IndexedWidgetBuilder类型必传参数,为给定索引创建Widget
      @required IndexedWidgetBuilder itemBuilder,
      //int类型可选命名参数,创建Widget的个数
      int itemCount,
      //...省略与ListView相同部分
    })
    
    //此构造方法采用 IndexedWidgetBuilder,一个是 itemBuilder,可以根据需要创建子 Widget,另一个是 separatorBuilder,同样构建出现在子项目之间的分隔子项目。此构造函数适用于具有固定数目的子元素的列表视图
    ListView.separated({
      Key key,
      //IndexedWidgetBuilder类型必传参数,为给定索引创建Widget
      @required IndexedWidgetBuilder itemBuilder,
      //IndexedWidgetBuilder类型必传参数,为给定索引创建Widget分割Widget
      @required IndexedWidgetBuilder separatorBuilder,
      //int类型必传参数,创建Widget的个数
      @required int itemCount,
      //...省略与ListView相同部分
    })
    
    //此构造方法采用 SliverChildDelegate,它提供了自定义模型的其他方面的功能。例如,SliverChildDelegate 可以控制用于估计实际不可见的子代大小的算法  
    const ListView.custom({
      Key key,
      //SliverChildDelegate类型必传参数,为ListView提供子Widget的委托
      @required this.childrenDelegate,
        //...省略与ListView相同部分
    })
    
    2、示例

    垂直列表

    class MyApp extends StatelessWidget {
      const MyApp({super.key});
    
      @override
      Widget build(BuildContext context) {
        return ListView(
          children: const [
            ListTile(
              title: Text("第一行"),
              subtitle: Text("第一行副标题"),
              titleTextStyle: TextStyle(
                color: Colors.red,
                backgroundColor: Colors.blue,
                fontSize: 30,
              ),
              subtitleTextStyle: TextStyle(
                color: Colors.green,
                backgroundColor: Colors.orange,
                fontSize: 10,
              ),
            ),
            ListTile(
              title: Text("第二行"),
              subtitle: Text("第二行副标题"),
              titleTextStyle: TextStyle(
                color: Colors.red,
                backgroundColor: Colors.blue,
                fontSize: 30,
              ),
              subtitleTextStyle: TextStyle(
                color: Colors.green,
                backgroundColor: Colors.orange,
                fontSize: 10,
              ),
            ),
          ],
        );
      }
    }
    
    class MyApp extends StatelessWidget {
      const MyApp({super.key});
    
      @override
      Widget build(BuildContext context) {
        return ListView(
          children: const [
            ListTile(
              leading: Icon(
                Icons.assignment,
                color: Colors.red,
                // size: 40,
              ),
              title: Text("全部订单"),
            ),
            Divider(),
            ListTile(
              leading: Icon(
                Icons.payment,
                color: Colors.green,
                // size: 40,
              ),
              title: Text("待付款"),
            ),
            Divider(),
            ListTile(
              leading: Icon(
                Icons.local_car_wash,
                color: Colors.orange,
                // size: 40,
              ),
              title: Text("待收货"),
            ),
            Divider(),
            ListTile(
              leading: Icon(
                Icons.favorite,
                color: Colors.lightGreen,
                // size: 40,
              ),
              title: Text("我的收藏"),
            ),
            Divider(),
            ListTile(
              leading: Icon(
                Icons.people,
                color: Colors.black54,
                // size: 40,
              ),
              title: Text("在线客服"),
            ),
            Divider(),
          ],
        );
      }
    }
    

    垂直图文列表

    class MyApp extends StatelessWidget {
      const MyApp({super.key});
      @override
      Widget build(BuildContext context) {
        return ListView(
          children: [
            ListTile(
              leading: Image.network("https://www.itying.com/images/flutter/1.png"),
              title: const Text("华北黄淮高温雨今起强势登场"),
              subtitle: const Text("中国天气网讯 21日开始,华北黄淮高温雨今起强势登场"),
            ),
            const Divider(),
            ListTile(
              trailing: Image.network("https://www.itying.com/images/flutter/1.png"),
              title: const Text("华北黄淮高温雨今起强势登场"),
              subtitle: const Text("中国天气网讯 21日开始,华北黄淮高温雨今起强势登场"),
            ),
            const Divider(),
            ListTile(
              leading: Image.network("https://www.itying.com/images/flutter/1.png"),
              title: const Text("华北黄淮高温雨今起强势登场"),
              // subtitle: const Text("中国天气网讯 21日开始,华北黄淮高温雨今起强势登场"),
            ),
            const Divider(),
          ],
        );
      }
    }
    
    class MyApp extends StatelessWidget {
      const MyApp({super.key});
    
      @override
      Widget build(BuildContext context) {
        return ListView(
          padding: const EdgeInsets.all(10),
          children: [
            Image.network("https://www.itying.com/images/flutter/1.png"),
            Container(
              height: 44,
              padding: const EdgeInsets.fromLTRB(0, 10, 0, 10),
              child: const Text(
                "第一行",
                textAlign: TextAlign.center,
                style: TextStyle(fontSize: 18),
              ),
            ),
            const Divider(),
            Image.network("https://www.itying.com/images/flutter/2.png"),
            Container(
              height: 44,
              padding: const EdgeInsets.fromLTRB(0, 10, 0, 10),
              child: const Text(
                "第二行",
                textAlign: TextAlign.center,
                style: TextStyle(fontSize: 18),
              ),
            ),
            const Divider(),
          ],
        );
      }
    }
    

    水平列表

    class MyApp extends StatelessWidget {
      const MyApp({super.key});
    
      @override
      Widget build(BuildContext context) {
        return SizedBox(
          height: 180,
          child: ListView(
            scrollDirection: Axis.horizontal,
            children: [
              ClipOval(
                //圆角
                child: Container(
                  width: 180,
                  color: Colors.red,
                ),
              ),
              Container(
                  width: 180,
                  color: Colors.green,
                  child: ClipRRect(
                    borderRadius: BorderRadius.circular(50),
                    child: Column(
                      children: [
                        Image.network(
                            "https://www.itying.com/images/flutter/1.png"),
                        const Text("第一个文本"),
                      ],
                    ),
                  )),
              Container(
                color: Colors.orange,
                width: 180,
              ),
            ],
          ),
        );
      }
    }
    

    动态列表

    class MyApp extends StatelessWidget {
      const MyApp({super.key});
    
      List<Widget> _initListView() {
        List<Widget> list = [];
        for (var i = 0; i < 10; i++) {
          list.add(const ListTile(
            title: Text("列表"),
          ));
        }
        return list;
      }
    
      @override
      Widget build(BuildContext context) {
        return ListView(
          children: _initListView(),
        );
      }
    }
    

    builder 实现动态列表

    class MyApp extends StatelessWidget {
      List<String> list = [];
      MyApp({super.key}) {
        for (var i = 0; i < 10; i++) {
          list.add("列表 -- $i");
        }
      }
    
      @override
      Widget build(BuildContext context) {
        return ListView.builder(
          itemCount: list.length,//数量
          itemBuilder: (BuildContext context, int index) {
            return ListTile(
              title: Text(list[index]),
            );
          },
        );
      }
    }
    

    builder 实现动态列表 -- 获取 json 数据

    // listData 中测试数据,使用时需要导入头文件
    List listData=[
          {
              "title": 'Candy Shop',
              "author": 'Mohamed Chahin',
              "imageUrl": 'https://www.itying.com/images/flutter/1.png',
          },
           {
              "title": 'Childhood in a picture',
              "author": 'Google',
              "imageUrl": 'https://www.itying.com/images/flutter/2.png',
          },
          {
              "title": 'Alibaba Shop',
              "author": 'Alibaba',
              "imageUrl": 'https://www.itying.com/images/flutter/3.png',
          },
          {
              "title": 'Candy Shop',
              "author": 'Mohamed Chahin',
              "imageUrl": 'https://www.itying.com/images/flutter/4.png',
          },
           {
              "title": 'Tornado',
              "author": 'Mohamed Chahin',
              "imageUrl": 'https://www.itying.com/images/flutter/5.png',
          },
          {
              "title": 'Undo',
              "author": 'Mohamed Chahin',
              "imageUrl": 'https://www.itying.com/images/flutter/6.png',
          },
          {
              "title": 'white-dragon',
              "author": 'Mohamed Chahin',
              "imageUrl": 'https://www.itying.com/images/flutter/7.png',
          }      
    
    ];
    
    class MyApp extends StatelessWidget {
      const MyApp({super.key});
    
      @override
      Widget build(BuildContext context) {
        return ListView.builder(
          itemCount: listData.length,
          itemBuilder: (BuildContext context, int index) {
            return ListTile(
              leading: Image.network(listData[index]["imageUrl"]),
              title: Text(listData[index]["title"]),
              subtitle: Text(listData[index]["author"]),
            );
          },
        );
      }
    }
    

    2、GridView

    GridView 网格布局,让可以滚动的元素使用矩阵方式排列(类似 OC 的 UICollectionView)。

    1、GridView 创建网格方式

    1、GridView.count 方式
    2、GridView.extent 方式
    3、GridView.builder 方式

    2、GridView 常见属性
    GridView GridView({
      Key? key,
      Axis scrollDirection = Axis.vertical,  //滚动方向
      //bool类型可选命名参数,用于设置视图的滚动方向是否为读取方向
      bool reverse = false,
      //ScrollController类型可选命名参数,控制滚动视图滚动位置的控制器
      ScrollController? controller,
      //bool类型可选命名参数,是否是与父PrimaryScrollController相关联的主滚动视图
      bool? primary,
      //ScrollPhysics类型可选命名参数,滚动视图应如何响应用户输入
      ScrollPhysics? physics,
      //boo类型可选命名参数,crollDirection中滚动视图的范围是否应由正在查看的内容确定
      bool shrinkWrap = false,
      EdgeInsetsGeometry? padding,  //内边距
      //控制布局,主要用在 GridView.builder 里面
      required SliverGridDelegate gridDelegate,
      //bool类型可选命名参数,是否将每个子Widget都包装在AutomaticKeepAlive组件中
      bool addAutomaticKeepAlives = true,
      //bool类型可选命名参数,是否将每个子Widget都包装在RepaintBoundary组件中
      bool addRepaintBoundaries = true,
      //bool类型可选命名参数,是否将每个子Widget都包装在IndexedSemantics组件中
      bool addSemanticIndexes = true,
      //double类型可选命名参数,用于设置不可见的缓存区域的大小
      double? cacheExtent,
      //List<Widget>类型可选命名参数,用于设置滚动列表的每一项Widget
      List<Widget> children = const <Widget>[],
      //int类型可选命名参数,为ListView中的子列表中Widget提供语义信息的数量
      int? semanticChildCount,
      //DragStartBehavior类型可选命名参数,确定处理拖动开始行为的方式
      DragStartBehavior dragStartBehavior = DragStartBehavior.start,
      //Clip类型可选命名参数,内容将被裁剪(或不裁剪)
      Clip clipBehavior = Clip.hardEdge,
      ScrollViewKeyboardDismissBehavior keyboardDismissBehavior = ScrollViewKeyboardDismissBehavior.manual,
      //保持滑动的偏移量
      String? restorationId,
    })
    
    3、网格布局

    GridView.count 实现网格布局
    GridView.count 构造函数内部使用了 SliverGridDelegateWithFixedCrossAxisCount,我们通过它可以快速的创建横轴固定数量子元素的 GridView。

    //示例一
    class MyApp extends StatelessWidget {
      const MyApp({super.key});
    
      @override
      Widget build(BuildContext context) {
        return GridView.count(
          crossAxisSpacing: 3,  //widget 左右间的距离
          mainAxisSpacing: 2,  //widget 上下间的距离
          crossAxisCount: 4, //每行列数
          children: const <Widget>[
            Icon(Icons.home),
            Icon(Icons.ac_unit),
            Icon(Icons.search),
            Icon(Icons.settings),
            Icon(Icons.airport_shuttle),
            Icon(Icons.all_inclusive),
            Icon(Icons.beach_access),
            Icon(Icons.cake),
            Icon(Icons.circle),
          ],
        );
      }
    }
    
    示例二
    ///GridView.count 实现网格布局
    class MyApp1 extends StatelessWidget {
      const MyApp1({super.key});
    
      List<Widget> _customList() {
        List<Widget> list = [];
        for (var i = 0; i < 50; i++) {
          list.add(
            Container(
              color: Colors.red,
              alignment: Alignment.center,
              child: Text(
                "第 $i 个元素",
                style: const TextStyle(color: Colors.white, fontSize: 15),
              ),
            ),
          );
        }
        return list;
      }
    
      @override
      Widget build(BuildContext context) {
        return GridView.count(
          padding: const EdgeInsets.all(10),
          crossAxisSpacing: 3, //水平子 Widget 之间间距
          mainAxisSpacing: 2, //垂直子 Widget 之间间距
          crossAxisCount: 4, //每行列数
          childAspectRatio: 0.8, //宽高比
          children: _customList(),
        );
      }
    }
    

    GridView.count 实现动态列表

    ///GridView.count 实现动态列表
    class MyApp extends StatelessWidget {
      const MyApp({super.key});
    
      List<Widget> _customList() {
        var list = listData.map((value) {
          return Container(
            decoration: BoxDecoration(
                border: Border.all(
              color: const Color.fromRGBO(233, 233, 233, 0.9),
              width: 1,
            )),
            child: Column(
              children: [
                Image.network(value["imageUrl"]),
                const SizedBox(
                  height: 12,
                ),
                Text(
                  value["title"],
                  textAlign: TextAlign.center,
                  style: const TextStyle(fontSize: 10),
                ),
              ],
            ),
          );
        });
        return list.toList();
      }
    
      @override
      Widget build(BuildContext context) {
        return GridView.count(
          crossAxisSpacing: 10,
          mainAxisSpacing: 10,
          crossAxisCount: 2,
          padding: const EdgeInsets.all(10),
          children: _customList(),
        );
      }
    }
    

    GridView.extent 实现网格布局
    GridView.extent 构造函数内部使用了 SliverGridDelegateWithMaxCrossAxisExtent,我们通过它可以快速的创建横轴子元素为固定最大长度的的 GridView。

    class MyApp extends StatelessWidget {
      const MyApp({super.key});
    
      @override
      Widget build(BuildContext context) {
        return GridView.extent(
          maxCrossAxisExtent: 100, //横轴子元素的最大长度
          children: const <Widget>[
            Icon(Icons.home),
            Icon(Icons.ac_unit),
            Icon(Icons.search),
            Icon(Icons.settings),
            Icon(Icons.airport_shuttle),
            Icon(Icons.all_inclusive),
            Icon(Icons.beach_access),
            Icon(Icons.cake),
            Icon(Icons.circle),
          ],
        );
      }
    }
    

    GridView.builder 实现动态列表

    
    ///GridView.builder 实现动态列表
    class MyApp extends StatelessWidget {
      const MyApp({super.key});
    
      //初始化数据
      Widget _customWidget(BuildContext context, int index) {
        return Container(
          decoration: BoxDecoration(
            border: Border.all(color: const Color.fromRGBO(233, 233, 233, 0.9)),
          ),
          child: Column(
            children: [
              Image.network(listData[index]["imageUrl"]),
              const SizedBox(
                height: 12,
              ),
              Text(
                listData[index]["title"],
                textAlign: TextAlign.center,
                style: const TextStyle(fontSize: 15),
              )
            ],
          ),
        );
      }
    
      @override
      Widget build(BuildContext context) {
        return GridView.builder(
          gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(//注意此行
            crossAxisCount: 2, //每行 widget 数量
            crossAxisSpacing: 10, //widget 水平之间的距离
            mainAxisSpacing: 10, //widget 垂直之间的距离
          ),
          itemCount: listData.length,
          itemBuilder: _customWidget,
        );
      }
    }
    
    class MyApp extends StatelessWidget {
      const MyApp({super.key});
    
      Widget _customWidget(BuildContext context, int index) {
        return Container(
          decoration: BoxDecoration(
              border: Border.all(
            color: const Color.fromRGBO(233, 233, 233, 0.9),
            width: 1,
          )),
          child: Column(
            children: [
              Image.network(listData[index]["imageUrl"]),
              const SizedBox(
                height: 12,
              ),
              Text(
                listData[index]["title"],
                textAlign: TextAlign.center,
                style: const TextStyle(
                  fontSize: 15,
                ),
              )
            ],
          ),
        );
      }
    
      @override
      Widget build(BuildContext context) {
        return GridView.builder(
          gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent(//注意此行
            maxCrossAxisExtent: 300, //横轴元素的最大长度
            crossAxisSpacing: 10, //widget 水平之间的距离
            mainAxisSpacing: 10, //widget 垂直之间的距离
          ),
          itemCount: listData.length,
          itemBuilder: _customWidget,
        );
      }
    }
    

    相关文章

      网友评论

          本文标题:Flutter 组件之 ListView、GridView

          本文链接:https://www.haomeiwen.com/subject/tkjnudtx.html