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'],);}
}
现在,我们将设计我们的小部件以支持水平、垂直和网格视图。
创建一个名为 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)),],),],),),)],),),);}
}
设计一个名为 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,),),)],),);}
}
最后,让我们为垂直视图创建一个小部件类。
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)),],),)],),);}
}
现在是时候把所有的小部件合并到一个屏幕中了,我们先创建一个名为“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],);}),],),),),);}
}
我使用了一个 SingleChildScrollView widget 作为代码中的顶部根 widget,考虑到我整合了多个布局,如水平列表、网格视图和垂直列表,我将所有这些 widget 包装在一个 Column widget 中。
挑战在于如何处理多个滚动部件,因为在上述示例中有两个垂直滚动部件:一个网格视图和一个垂直列表视图。为了禁用单个部件的滚动行为, physics 属性被设置为 const NeverScrollableScrollPhysics()。取而代之的是,使用顶层根 SingleChildScrollView`` 来启用整个内容的滚动。此外,SingleChildScrollView上的shrinkWrap属性被设置为true`,以确保它能紧紧包裹其内容,只占用其子控件所需的空间。
Github 链接:https://github.com/tarunaronno005/flutter-multiple-listview
相关文章:
Flutter 中在单个屏幕上实现多个列表
今天,我将提供一个实际的示例,演示如何在单个页面上实现多个列表,这些列表可以水平排列、网格格式、垂直排列,甚至是这些常用布局的组合。 下面是要做的: 实现 让我们从创建一个包含产品所有属性的产品模型开始。 …...
YOLOv8 加持 MobileNetv3,目标检测新篇章
🗝️YOLOv8实战宝典--星级指南:从入门到精通,您不可错过的技巧 -- 聚焦于YOLO的 最新版本, 对颈部网络改进、添加局部注意力、增加检测头部,实测涨点 💡 深入浅出YOLOv8:我的专业笔记与技术总结 -- YOLOv8轻松上手, 适用技术小白,文章代码齐全,仅需 …...
.gitignore 文件——如何在 Git 中忽略文件和文件夹详细教程
文章目录 什么是 .gitignore 文件?.gitignore 文件是用来做什么的?如何创建一个 .gitignore 文件?在 .gitignore 文件中应包括什么?如何在 Git 中忽略一个文件和文件夹如何忽略以前提交的文件 什么是 .gitignore 文件?…...
【数据结构(二)】单链表(3)
文章目录 1. 链表介绍2. 单链表应用实例2.1. 顺序添加方式2.1.1. 思路分析2.1.2. 代码实现 2.2. 按照编号顺序添加方式2.2.1. 思路分析2.2.2. 代码实现 3. 单链表节点的修改3.1. 思路分析3.2. 代码实现 4. 单链表节点的删除4.1. 思路分析4.2. 代码实现 5. 单链表常见面试题5.1.…...
创新案例|云服务平台HashiCorp是如何构建开源社区实现B2B增长飞轮
社区文化是HashiCorp企业文化的重要组成部分。虽然众多公司声称自己是社区驱动,但实际付诸行动的很少。与众不同的是,HashiCorp从一开始就将社区视为战略方针的核心,这也影响和塑造了公司今天的发展方向。社区不仅是执行策略之一,…...
2024年软件测试面试必看系列,看完去面试你会感谢我的!!
朋友圈点赞的测试用例 功能测试 1点赞后是否显示结果 2.点赞后是否可以取消; 3.点赞取消后是否可以重复点赞; 4.共同好友点赞后,是否有消息提醒; 5.非共同好友点赞后,是否有消息提醒; 6.点击点赞人昵称,是否可以跳转到他/她的主页; 7.自己能…...
01ctfer 文件上传
01ctfer 文件上传 启动靶场 访问该地址 代码审计 <?php header("Content-Type:text/html; charsetutf-8"); // 每5分钟会清除一次目录下上传的文件 require_once(pclzip.lib.php);if(!$_FILES){echo <!DOCTYPE html> <html lang"zh">…...
2.2 调用星火大模型的API
调用星火大模型的API 1 申请API调用权限:2 调用原生星火 API3 统一API调用方式 项目仓库地址:https://github.com/datawhalechina/llm-universe 讯飞星火认知大模型,由科大讯飞于2023年5月推出的中文大模型,也是国内大模型的代表…...
云原生是整个信息化行业的未来,一文彻底搞懂云原生
云原生这个词来自英语的Cloud Native的翻译,云原生是已经存多年在术语,真正开始获得关注的是在2015年到2016年。 这归因于这几年逐渐发布的Docker的兴起。 会有越来越多的企业和组织开始关注到它,并把他们的工作负载运行在云端的益处。无论是…...
【Redis】RedisTemplate最全的常用方法
文章目录 前言1.RedisTemplate常用方法2.String类型3.Hash类型4.List类型5.Set类型6.zSet类型 前言 RedisTemplate常用方法String类型Hash类型List类型Set类型zSet类型 Redis常用的数据类型:String、Hash、List、Set、zSet 1.RedisTemplate常用方法 redisTempla…...
图像倾斜角度求取-Radon变换
Radon算法 Radon(拉东)算法是一种通过定方向投影叠加,找到最大投影值时角度,从而确定图像倾斜角度的算法。具体过程如图所示 图1 Radon变换算法 Radon计算示例 对于纹理方向明显的图像,如图2所示,可以通…...
如何在本地搭建Oracle数据库实现公网环境下通过PLSQL工具进行远程访问
文章目录 前言1. 数据库搭建2. 内网穿透2.1 安装cpolar内网穿透2.2 创建隧道映射 3. 公网远程访问4. 配置固定TCP端口地址4.1 保留一个固定的公网TCP端口地址4.2 配置固定公网TCP端口地址4.3 测试使用固定TCP端口地址远程Oracle 前言 Oracle,是甲骨文公司的一款关系…...
时序预测 | Python实现ConvLSTM卷积长短期记忆神经网络股票价格预测(Conv1D-LSTM)
时序预测 | Python实现ConvLSTM卷积长短期记忆神经网络股票价格预测(Conv1D-LSTM) 目录 时序预测 | Python实现ConvLSTM卷积长短期记忆神经网络股票价格预测(Conv1D-LSTM)预测效果基本介绍程序设计参考资料预测效果 基本介绍 时序预测 | Python实现ConvLSTM卷积长短期记忆神…...
qtpdfium的编译及读取pdf文件和一些简单操作
qtpdfium是谷歌的一款开源项目,它的内核是基于国内的福昕pdf,许可协议为 BSD 3-Clause,允许用于闭源商业行为 下载 我们可以从git上进行下载,github,如果嫌下载速度慢,可以从csdn进行下载csdn 下载完成之…...
ClickHouse查看执行计划
在clickhouse 20.6版本之前要查看SQL语句的执行计划需要设置日志级别为trace才能可以看到,并且只能真正执行sql,在执行日志里面查看。在20.6版本引入了原生的执行计划的语法。在20.6.3版本成为正式版本的功能。 本文档基于目前较新稳定版21.7.3.14。 1.基…...
2023-11-17 VsCode使用makefile进行多文件编译
点击 <C 语言编程核心突破> 快速C语言入门 VsCode使用makefile进行多文件编译 前言一、一个简单的多文件示例二、makefile基本语法三、VsCode使用makefile总结 前言 要解决问题: C或C可以多文件编译, 意味着需要进行代码组织, 为了方便多文件编译, gnu开发了make工具, …...
Network(四)NAT实现方式与VRRP概述
一 NAT 1 NAT概述 (1)NAT的作用 Network Address Translation,网络地址转换 通过将内部网络的私有IP地址转换成全球唯一的公网IP地址使内部网络可以连接到互联网。 (2)私有IP地址分类 A类10.0.0.0~10.255.255.…...
C#_键盘钩子
一、class class KeyboardHook{public event KeyEventHandler KeyDownEvent;public event KeyPressEventHandler KeyPressEvent;public event KeyEventHandler KeyUpEvent;public delegate int HookProc(int nCode, Int32 wParam, IntPtr lParam);static int hKeyboardHook 0;…...
YOLO免费数据集网站收集
目录 Roboflow Universe: Open Source Computer Vision Community Find Open Datasets and Machine Learning Projects | Kaggle 编辑 【火焰和烟雾图像数据集】-计算机视觉数据集-极市开发者平台 (cvmart.net) 开放数据集- 飞桨AI Studio星河社区 - 人工智能学习与实训社…...
拼图小游戏
package li;import ui.tu; //启动类 public class 主 {public static void main(String[] args) {new tu(); //创建登陆界面} }package ui;import javax.swing.*; import javax.swing.border.BevelBorder; import java.awt.event.ActionEvent; import java.awt.event.ActionLi…...
智慧医疗能源事业线深度画像分析(上)
引言 医疗行业作为现代社会的关键基础设施,其能源消耗与环境影响正日益受到关注。随着全球"双碳"目标的推进和可持续发展理念的深入,智慧医疗能源事业线应运而生,致力于通过创新技术与管理方案,重构医疗领域的能源使用模式。这一事业线融合了能源管理、可持续发…...
基于Flask实现的医疗保险欺诈识别监测模型
基于Flask实现的医疗保险欺诈识别监测模型 项目截图 项目简介 社会医疗保险是国家通过立法形式强制实施,由雇主和个人按一定比例缴纳保险费,建立社会医疗保险基金,支付雇员医疗费用的一种医疗保险制度, 它是促进社会文明和进步的…...
基于数字孪生的水厂可视化平台建设:架构与实践
分享大纲: 1、数字孪生水厂可视化平台建设背景 2、数字孪生水厂可视化平台建设架构 3、数字孪生水厂可视化平台建设成效 近几年,数字孪生水厂的建设开展的如火如荼。作为提升水厂管理效率、优化资源的调度手段,基于数字孪生的水厂可视化平台的…...
Robots.txt 文件
什么是robots.txt? robots.txt 是一个位于网站根目录下的文本文件(如:https://example.com/robots.txt),它用于指导网络爬虫(如搜索引擎的蜘蛛程序)如何抓取该网站的内容。这个文件遵循 Robots…...
第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词
Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵,其中每行,每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid,其中有多少个 3 3 的 “幻方” 子矩阵&am…...
全志A40i android7.1 调试信息打印串口由uart0改为uart3
一,概述 1. 目的 将调试信息打印串口由uart0改为uart3。 2. 版本信息 Uboot版本:2014.07; Kernel版本:Linux-3.10; 二,Uboot 1. sys_config.fex改动 使能uart3(TX:PH00 RX:PH01),并让boo…...
Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信
文章目录 Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket(服务端和客户端都要)2. 绑定本地地址和端口&#x…...
PHP 8.5 即将发布:管道操作符、强力调试
前不久,PHP宣布了即将在 2025 年 11 月 20 日 正式发布的 PHP 8.5!作为 PHP 语言的又一次重要迭代,PHP 8.5 承诺带来一系列旨在提升代码可读性、健壮性以及开发者效率的改进。而更令人兴奋的是,借助强大的本地开发环境 ServBay&am…...
tomcat入门
1 tomcat 是什么 apache开发的web服务器可以为java web程序提供运行环境tomcat是一款高效,稳定,易于使用的web服务器tomcathttp服务器Servlet服务器 2 tomcat 目录介绍 -bin #存放tomcat的脚本 -conf #存放tomcat的配置文件 ---catalina.policy #to…...
libfmt: 现代C++的格式化工具库介绍与酷炫功能
libfmt: 现代C的格式化工具库介绍与酷炫功能 libfmt 是一个开源的C格式化库,提供了高效、安全的文本格式化功能,是C20中引入的std::format的基础实现。它比传统的printf和iostream更安全、更灵活、性能更好。 基本介绍 主要特点 类型安全:…...
