• Flutter 中在单个屏幕上实现多个列表


    今天,我将提供一个实际的示例,演示如何在单个页面上实现多个列表,这些列表可以水平排列、网格格式、垂直排列,甚至是这些常用布局的组合。

    下面是要做的:
    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

    实现

    让我们从创建一个包含产品所有属性的产品模型开始。

    class Product {
      final String id;
      final String name;
      final double price;
      final String image;
    
      const Product({
        required this.id,
        required this.name,
        required this.price,
        required this.image,
      });
    
      factory Product.fromJson(Map json) {
        return Product(
          id: json['id'],
          name: json['name'],
          price: json['price'],
          image: json['image'],
        );
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    现在,我们将设计我们的小部件以支持水平、垂直和网格视图

    创建一个名为 HorizontalRawWidget 的新窗口小部件类,定义水平列表的用户界面

    import 'package:flutter/material.dart';
    import 'package:multiple_listview_example/models/product.dart';
    
    class HorizontalRawWidget extends StatelessWidget {
      final Product product;
    
      const HorizontalRawWidget({Key? key, required this.product})
          : super(key: key);
    
      
      Widget build(BuildContext context) {
        return Padding(
          padding: const EdgeInsets.only(
            left: 15,
          ),
          child: Container(
            width: 125,
            decoration: BoxDecoration(
                color: Colors.white, borderRadius: BorderRadius.circular(12)),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Padding(
                  padding: const EdgeInsets.fromLTRB(5, 5, 5, 0),
                  child: ClipRRect(
                    borderRadius: BorderRadius.circular(12),
                    child: Image.network(
                      product.image,
                      height: 130,
                      fit: BoxFit.contain,
                    ),
                  ),
                ),
                Expanded(
                  child: Padding(
                    padding: const EdgeInsets.all(8.0),
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        Expanded(
                          child: Text(product.name,
                              maxLines: 2,
                              overflow: TextOverflow.ellipsis,
                              style: const TextStyle(
                                  color: Colors.black,
                                  fontSize: 12,
                                  fontWeight: FontWeight.bold)),
                        ),
                        Row(
                          crossAxisAlignment: CrossAxisAlignment.end,
                          children: [
                            Text("\$${product.price}",
                                style: const TextStyle(
                                    color: Colors.black, fontSize: 12)),
                          ],
                        ),
                      ],
                    ),
                  ),
                )
              ],
            ),
          ),
        );
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66

    设计一个名为 GridViewRawWidget 的小部件类,定义单个网格视图的用户界面。

    import 'package:flutter/material.dart';
    import 'package:multiple_listview_example/models/product.dart';
    
    class GridViewRawWidget extends StatelessWidget {
      final Product product;
    
      const GridViewRawWidget({Key? key, required this.product}) : super(key: key);
    
      
      Widget build(BuildContext context) {
        return Container(
          padding: const EdgeInsets.all(5),
          decoration: BoxDecoration(
              color: Colors.white, borderRadius: BorderRadius.circular(10)),
          child: Column(
            children: [
              AspectRatio(
                aspectRatio: 1,
                child: ClipRRect(
                  borderRadius: BorderRadius.circular(10),
                  child: Image.network(
                    product.image,
                    fit: BoxFit.fill,
                  ),
                ),
              )
            ],
          ),
        );
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    最后,让我们为垂直视图创建一个小部件类。

    import 'package:flutter/material.dart';
    import 'package:multiple_listview_example/models/product.dart';
    
    class VerticalRawWidget extends StatelessWidget {
      final Product product;
    
      const VerticalRawWidget({Key? key, required this.product}) : super(key: key);
    
      
      Widget build(BuildContext context) {
        return Container(
          margin: const EdgeInsets.symmetric(horizontal: 15, vertical: 5),
          padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 10),
          color: Colors.white,
          child: Row(
            children: [
              Image.network(
                product.image,
                width: 78,
                height: 88,
              ),
              const SizedBox(
                width: 15,
              ),
              Expanded(
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text(
                      product.name,
                      style: const TextStyle(fontSize: 12, color: Colors.black, fontWeight: FontWeight.bold),
                    ),
                    SizedBox(
                      height: 5,
                    ),
                    Text("\$${product.price}",
                        style: const TextStyle(color: Colors.black, fontSize: 12)),
                  ],
                ),
              )
            ],
          ),
        );
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    现在是时候把所有的小部件合并到一个屏幕中了,我们先创建一个名为“home_page.dart”的页面,在这个页面中,我们将使用一个横向的 ListView、纵向的 ListView 和 GridView。

    import 'package:flutter/material.dart';
    import 'package:multiple_listview_example/models/product.dart';
    import 'package:multiple_listview_example/utils/product_helper.dart';
    import 'package:multiple_listview_example/views/widgets/gridview_raw_widget.dart';
    import 'package:multiple_listview_example/views/widgets/horizontal_raw_widget.dart';
    import 'package:multiple_listview_example/views/widgets/title_widget.dart';
    import 'package:multiple_listview_example/views/widgets/vertical_raw_widget.dart';
    
    class HomePage extends StatelessWidget {
      const HomePage({Key? key}) : super(key: key);
    
      
      Widget build(BuildContext context) {
        List products = ProductHelper.getProductList();
        return Scaffold(
          backgroundColor: const Color(0xFFF6F5FA),
          appBar: AppBar(
            centerTitle: true,
            title: const Text("Home"),
          ),
          body: SingleChildScrollView(
            child: Container(
              padding: const EdgeInsets.symmetric(vertical: 20),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  const TitleWidget(title: "Horizontal List"),
                  const SizedBox(
                    height: 10,
                  ),
                  SizedBox(
                    height: 200,
                    child: ListView.builder(
                        shrinkWrap: true,
                        scrollDirection: Axis.horizontal,
                        itemCount: products.length,
                        itemBuilder: (BuildContext context, int index) {
                          return HorizontalRawWidget(
                            product: products[index],
                          );
                        }),
                  ),
                  const SizedBox(
                    height: 10,
                  ),
                  const TitleWidget(title: "Grid View"),
                  Container(
                    padding:
                        const EdgeInsets.symmetric(horizontal: 15, vertical: 10),
                    child: GridView.builder(
                        gridDelegate:
                            const SliverGridDelegateWithFixedCrossAxisCount(
                                crossAxisCount: 2,
                                crossAxisSpacing: 13,
                                mainAxisSpacing: 13,
                                childAspectRatio: 1),
                        itemCount: products.length,
                        shrinkWrap: true,
                        physics: const NeverScrollableScrollPhysics(),
                        itemBuilder: (BuildContext context, int index) {
                          return GridViewRawWidget(
                            product: products[index],
                          );
                        }),
                  ),
                  const TitleWidget(title: "Vertical List"),
                  ListView.builder(
                      itemCount: products.length,
                      shrinkWrap: true,
                      physics: const NeverScrollableScrollPhysics(),
                      itemBuilder: (BuildContext context, int index) {
                        return VerticalRawWidget(
                          product: products[index],
                        );
                      }),
                ],
              ),
            ),
          ),
        );
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82

    我使用了一个 SingleChildScrollView widget 作为代码中的顶部根 widget,考虑到我整合了多个布局,如水平列表、网格视图和垂直列表,我将所有这些 widget 包装在一个 Column widget 中。

    挑战在于如何处理多个滚动部件,因为在上述示例中有两个垂直滚动部件:一个网格视图和一个垂直列表视图。为了禁用单个部件的滚动行为, physics 属性被设置为 const NeverScrollableScrollPhysics()。取而代之的是,使用顶层根 SingleChildScrollView`` 来启用整个内容的滚动。此外,SingleChildScrollView上的shrinkWrap属性被设置为true`,以确保它能紧紧包裹其内容,只占用其子控件所需的空间。

    Github 链接:https://github.com/tarunaronno005/flutter-multiple-listview

  • 相关阅读:
    Spring Boot(七)
    js 把对象转为字符串,并以逗号隔开
    MobaXterm如何连接CentOS7的Linux虚拟机?Redis可视化客户端工具如何连接Linux版Redis?
    vue 预览视频
    HDFS文件上传之create创建过程-尚硅谷大数据培训
    Dify后端源码目录结构和蓝图
    springcloud:3.1介绍雪崩和Resilience4j
    【原创】K8S环境下研发如何本地调试?kt-connect使用详解
    java计算机毕业设计Web企业差旅在线管理系统源码+mysql数据库+系统+lw文档+部署
    电影院订票选座小程序|基于微信小程序的电影院购票系统设计与实现(源码+数据库+文档)
  • 原文地址:https://blog.csdn.net/duninet/article/details/134445367