当前位置: 首页 > news >正文

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

http://www.lryc.cn/news/235835.html

相关文章:

  • YOLOv8 加持 MobileNetv3,目标检测新篇章
  • .gitignore 文件——如何在 Git 中忽略文件和文件夹详细教程
  • 【数据结构(二)】单链表(3)
  • 创新案例|云服务平台HashiCorp是如何构建开源社区实现B2B增长飞轮
  • 2024年软件测试面试必看系列,看完去面试你会感谢我的!!
  • 01ctfer 文件上传
  • 2.2 调用星火大模型的API
  • 云原生是整个信息化行业的未来,一文彻底搞懂云原生
  • 【Redis】RedisTemplate最全的常用方法
  • 图像倾斜角度求取-Radon变换
  • 如何在本地搭建Oracle数据库实现公网环境下通过PLSQL工具进行远程访问
  • 时序预测 | Python实现ConvLSTM卷积长短期记忆神经网络股票价格预测(Conv1D-LSTM)
  • qtpdfium的编译及读取pdf文件和一些简单操作
  • ClickHouse查看执行计划
  • 2023-11-17 VsCode使用makefile进行多文件编译
  • Network(四)NAT实现方式与VRRP概述
  • C#_键盘钩子
  • YOLO免费数据集网站收集
  • 拼图小游戏
  • 卷积神经网络(CNN)天气识别
  • Linux进程间通信之匿名管道
  • 【PTA题目】6-19 使用函数输出指定范围内的Fibonacci数 分数 20
  • 运行ps显示msvcp140.dll丢失怎么恢复?msvcp140.dll快速解决的4个不同方法
  • Java多线程(3)
  • Java线程周期
  • map与set的封装
  • mac无法向移动硬盘拷贝文件怎么解决?不能读取移动硬盘文件怎么解决
  • 基于Netty实现的简单聊天服务组件
  • 视频封面:从视频中提取封面,轻松制作吸引人的视频
  • CICD 持续集成与持续交付——gitlab