Flutter项目实战之女装商城------添加轮播图、分类导航、商品推荐、广告位处理、底部商品

本文主要是介绍Flutter项目实战之女装商城------添加轮播图、分类导航、商品推荐、广告位处理、底部商品,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言:

时间飞逝,伴随着打工人春节的结束心也得跟着回收一下,新年新气象,今年也没有什么高大上的目标,暂且先把去年落下的各种课程的学习给完整结束了,不过计划还是会再多学点其它新的东东,到时看情况,年后的第一次学习从之前落下的Flutter开始。

距离上一次Flutter项目实战之女装商城------首页设计分析、数据准备、Dio请求处理、接口配置、请求首页数据 - cexo - 博客园的学习已经时隔4个月之久了,先来回忆一下当时APP的样子做到了哪了:

其实要注意,后台数据是用的node来搭建的,注意本地先npm start一下:

然后本机ip会随时变动,记得根据本机当前的ip,将代码修改一下,比如:

基本也就搭了个架子,接下来则从首页开始继续往下撸。

添加轮播图:

效果:

接下来先来搭建一下首页的商品轮播图,样子如下:

添加依赖:

要实现这样的效果,当然得借助于三方库喽,这里使用flutter_swiper,官方地址:flutter_swiper | Flutter Package,

先来在工程中添加依赖:

构建轮播组件:

1、导包:

先来对home_page的代码进行一个全局回顾,目前长这样子:

import 'dart:convert';import 'package:flutter/material.dart';
import 'package:flutter_easyrefresh/easy_refresh.dart';
import 'package:fluttershop/config/color.dart';
import 'package:fluttershop/config/string.dart';
import 'package:fluttershop/service/http_service.dart';
import 'package:flutter_swiper/flutter_swiper.dart';class HomePage extends StatefulWidget {@override_HomePageState createState() => _HomePageState();
}class _HomePageState extends State<HomePage>with AutomaticKeepAliveClientMixin {//这里只是做一个演示,其实是不用加这个的,因为咱们的BottomNavigationBar是由IndexedStack构建的,具体参考index_page.dart文件@overridebool get wantKeepAlive => true;GlobalKey<ClassicalFooterWidgetState> _footerKey =GlobalKey<ClassicalFooterWidgetState>();@overridevoid initState() {super.initState();print('home_page.initState()');}@overrideWidget build(BuildContext context) {print('home_page.build()');return Scaffold(backgroundColor: Color.fromRGBO(244, 245, 245, 1.0),appBar: AppBar(title: Text(KString.homeTitle),centerTitle: true,),body: FutureBuilder(future: request('homePageContext', formData: null),builder: (context, snapshot) {if (snapshot.hasData) {var data = json.decode(snapshot.data.toString());print("gethomePageContext data:${data}");var dataList = data['data'];List<Map> swiperDataList =(dataList['slides'] as List).cast(); //轮播图List<Map> navigatorList =(dataList['category'] as List).cast(); //分类List<Map> recommendList =(dataList['recommend'] as List).cast(); //商品推荐List<Map> floor1 = (dataList['floor1'] as List).cast(); //底部商品推荐Map fp1 = dataList['floor1Pic']; //广告return EasyRefresh.custom(enableControlFinishRefresh: false,enableControlFinishLoad: true,footer: ClassicalFooter(key: _footerKey,bgColor: Colors.white,textColor: KColor.refreshTextColor,infoColor: KColor.refreshTextColor,noMoreText: '',//加载中...loadingText: KString.loading,loadReadyText: KString.loadReadyText,),slivers: [SliverList(delegate: SliverChildBuilderDelegate((context, index) {return Container(width: 60.0,height: 60.0,child: Center(child: Text('$index'),),color: index % 2 == 0? Colors.grey[300]: Colors.transparent,);},childCount: 5,),),],onLoad: () async {print('开始加载更多');//TODO 执行下一页的请求},);} else {return Center(child: Text('加载中...'),);}}),);}
}

此时需要用ListView来构建整个界面的内容,所以代码需要修改一下:

2、编写Swiper组件框架:

其中注意Dart的语法,我在编写这块时都感觉完全生疏了,时间一长工作中又不用铁定健忘,这时之前学习留下的笔记就发挥它的威力了,这里说的Dart语法就是构造函数相关,一个是:

关于它可以回忆Fluter基础巩固之Dart语言详解<二> - cexo - 博客园,

另一个是在它定义构造时用了一个大括号:

这又是啥语法呢?可选命名参数,如果忘了可以参考Fluter基础巩固之Dart语言详解<一> - cexo - 博客园,如下:

3、具体编写Swiper组件:

接下来具体编写Swpier组件的构建,先来参考官方的DEMO:

这里就一气呵成了,只对关键地方做下说明:

其中关于fit属性有很多种,这里参考大佬的Flutter中 BoxFit 的几种样式说明,贴出来为我所用:

BoxFit.contain

将会尽可能的伸展来达到组件的边缘。

Flutter中 BoxFit 的几种样式

BoxFit.cover

将会尽可能小的放大来铺满整个组件

Flutter中 BoxFit 的几种样式

BoxFit.fill

通过拉伸(改变原图比例)来铺满组件

Flutter中 BoxFit 的几种样式

BoxFit.fitHeight

保持原图比例,拉升高度来达到组件的高度

Flutter中 BoxFit 的几种样式

BoxFit.fitWidth

保持原图比例,拉升宽度来达到组件的宽度

Flutter中 BoxFit 的几种样式

BoxFit.none

正常展示,默认居中。

Flutter中 BoxFit 的几种样式

BoxFit.scaleDown

保持在组件中并且不改变比例

Flutter中 BoxFit 的几种样式

另外还有一个关于设置尺寸的代码:

这块是屏幕适配的写法,记得不要直接写死一个值,关于这块可以回忆博文阅读密码验证 - 博客园,不过多解释。

然后需要设置里面小红点和自动轮播,很简单:

4、运行:

呃,咋图片没加载出来空白了呢?这里要注意了【以后这块就不强调了】!!!然后看一下每个图片的url是这么个形式:

因为node服务是运行在电脑上的,127.0.0.1代表的是电脑的本机ip,但是!!!我运行是在真机上,而非电脑上开设的模拟器,那很显然在手机上是无法通过127.0.0.1这个电脑端的本地地址来访问图片了,解决办法也很简单,直接用电脑的局域网ip既可,查看一下电脑的ip:

然后看一下目前咱们node的baseurl的ip是:

当然这个ip可能随着网络的变化会不断变化,所以以后在学习之前一定先要确保ip地址是正确的,再重启一下npm,然后再运行就ok了:

效果如下:

嗯,不错~~整体也比较简单。

分类导航:

效果:

其中图标都是后台返的,另外最多就支持10个分类,如果超过10个则需要截取。

具体实现:

1、列表中增加一个widget:

2、使用GridView来构建:

对于分类这种网络布局可以使用Flutter自带的GridView来进行构建,关于它的用法可以参考开启Fluter基础之旅<二>-------Future再论、常用组件、Material Design风格组件学习 - cexo - 博客园,下面来构建一下:

这块比较简单,其中标红的在设置大小时都用到了EdgeInsets这个类,这个在之前的学习中也大量用到了,看一下这个类的官方解释:

总之就是对于方便给一个元素设置左右上下的间隙,而它比较经典的方法有Flutter之EdgeInsets_u013095264的博客-CSDN博客:

关于这块要记得熟练运用,另外对于GridView的这个属性也稍加说明一下:

其中physics是Flutter中的动画的一个种类,回忆一下开启Fluter基础之旅<四>-------表格、动画、手势 - cexo - 博客园:

而常见的physics有很多,看一下它的子类便可以了解:

这块就点一下,可以在之后慢慢了解。

接下来则来设置一下GridView的item项:

那如何构建呢?如下:

接下来就来构建一下列表项,由于它也是需要可以进行点击的,所以依然用InkWell,比较简单,贴出来:

Widget _gridViewItemUI(BuildContext context, item, index) {return InkWell(onTap: () {//TODO 商品分类点击进详情},child: Column(children: [Image.network(item['image'],width: ScreenUtil().setWidth(95),),Text(item['firstCategoryName']),],),);}

接下来运行一下,看有木有问题,发现报错了。。

看IDE报错的详情:

其实是犯了一个低级错,啥错呢?

再运行一下:

商品推荐:

效果:

 当然是支持左右滑动了。

具体实现:

1、列表中增加一个widget:

//商品推荐组件
class RecommendUI extends StatelessWidget {final List<Map> recommendList;RecommendUI({Key key, this.recommendList}) : super(key: key);@overrideWidget build(BuildContext context) {return null;}
}

2、准备推荐商品标题widget:

先来准备子widget,布局也就是按从局部到整体的思路一步步来进行,也就是推荐的标题,如下:

其中涉及到几个色值和字符串,提到公共的地方为:

3、准备推荐商品列表widget:

目前先简单显示一个文本,先将整个界面架子组拼起来。

4、将子widget组拼起来:

接下来整体看一下基本架子的样子:

5、准备列表item的widget:

//列表itemWidget _item(context, index) {return InkWell(onTap: () {//TODO 商品点击进详情},child: Container(width: ScreenUtil().setWidth(200),padding: EdgeInsets.all(0.0),decoration: BoxDecoration(color: Colors.white,border: Border(left: BorderSide(width: 0.5, color: KColor.defaultBorderColor),)),child: Column(children: [Image.network(recommendList[index]['image']),//打折价格Text('¥${recommendList[index]['presentPrice']}',style: TextStyle(color: KColor.presentPriceTextColor),),//原价Text('¥${recommendList[index]['oriPrice']}',style: KFont.oriPriceStyle,),],),),);

其中配置相关的属性如下:

其中对于有中划线的原价以后在多处页面都可能会用到,所以这里对这样的样式字体进行一个抽取:

接下来运行看一下效果:

细节调整:

细节一:防止溢出处理

看这张图:

其实这里加一个防溢出的代码既可,如下:

再运行:

看一下它的作用:

细节二:图片压缩调整

目前对于这张图很不和谐:

此时就需要给图片增加压缩属性:

再看效果:

貌似上下木有间隙,看着有点别扭,因为有处笔误写错了:

修改一下:

再来看一下:

关于Image的几种压缩效果自己一个个试就成,不需要记,做得多了也就知道其它的意思了,就类似于Android的ImageView控件一样,它的缩放方式也很多,实际中还得根据产品的需求自己去尝试调试,具体这块的属性可以参考:Flutter中Image的fit属性解析 - 简书。

广告位处理:

效果:

就是一张纯图,没啥逻辑。

具体实现: 

1、准备商品广告widget:

这块比较简单,直接贴出:

//商品推荐中间广告
class FloorPic extends StatelessWidget {final Map floorPic;FloorPic({Key key, this.floorPic}) : super(key: key);@overrideWidget build(BuildContext context) {return Container(margin: EdgeInsets.only(top: 10.0),child: InkWell(onTap: () {//TODO 商品点击进详情},child: Image.network(floorPic['PICTURE_ADDRESS'],fit: BoxFit.cover,),));}
}

2、运行:

底部商品:

效果:

貌似这布局有点复杂,其实这里是涉及到row和column的嵌套布局,也是实际项目中会经常用到的一种布局方式,通过这个模块的编写正好可以掌握这种布局方法。

具体实现:

1、列表中增加一个widget:

//商品推荐下层
class Floor extends StatelessWidget {final List<Map> floor;Floor({Key key, this.floor}) : super(key: key);@overrideWidget build(BuildContext context) {return Container();}
}

2、使用Row来搭建左右两列效果:

3、具体构建五大子widget:

先来构建左边上面大图:

比较简单,接下来四个就依葫芦画瓢了,当然间隙需要稍加修改一下,一口气呵成:

//商品推荐下层
class Floor extends StatelessWidget {final List<Map> floor;Floor({Key key, this.floor}) : super(key: key);//跳转到商品详情void jumpDetail(context, String goodId) {//TODO}@overrideWidget build(BuildContext context) {return Container(child: Row(children: [//左侧商品Expanded(child: Column(children: [//左上图Container(padding: EdgeInsets.only(top: 4),height: ScreenUtil().setHeight(400),child: InkWell(onTap: () {jumpDetail(context, floor[0]['goodsId']);},child: Image.network(floor[0]['image'],fit: BoxFit.cover,)),),//左下图Container(padding: EdgeInsets.only(top: 1, right: 1),height: ScreenUtil().setHeight(200),child: InkWell(onTap: () {jumpDetail(context, floor[1]['goodsId']);},child: Image.network(floor[1]['image'],fit: BoxFit.cover,)),),],),),//右侧商品Expanded(child: Column(children: [//右上图Container(padding: EdgeInsets.only(top: 4, left: 1, bottom: 1),height: ScreenUtil().setHeight(200),child: InkWell(onTap: () {jumpDetail(context, floor[2]['goodsId']);},child: Image.network(floor[2]['image'],fit: BoxFit.cover,)),),//右中图Container(padding: EdgeInsets.only(top: 1, left: 1),height: ScreenUtil().setHeight(200),child: InkWell(onTap: () {jumpDetail(context, floor[3]['goodsId']);},child: Image.network(floor[3]['image'],fit: BoxFit.cover,)),),//右下图Container(padding: EdgeInsets.only(top: 1, left: 1),height: ScreenUtil().setHeight(200),child: InkWell(onTap: () {jumpDetail(context, floor[4]['goodsId']);},child: Image.network(floor[4]['image'],fit: BoxFit.cover,)),),],),),],),);}
}

4、给Row设置属性:

最后还需要给Row设置两个属性,如下:

mainAxisAlignment:

其中它有很多选项:

其中只需要对spaceBetween、spaceAround、spaceEvenly进行了解既可,具体啥意思可以参考这位大佬的Flutter学习之MainAxisAlignment属性详解_bkysdc的博客-CSDN博客,介绍还是蛮详细的,其中盗个图:

三者文字简述如下:

  • spaceBetween:

  • spaceAround:

  • spaceEvenly:

对于这些属性的理解还得在以后项目中的使用中来慢慢消化。

mainAxisSize:

其中它也有两个选项:

啥意思呢?目前还是找度娘线性布局Row和Column - 小图教父 - 博客园【关于这些涉及到木有接触过的知识点以后有时间整体单独成篇再细致的研究一下,目前先直接网上一大抄来解决疑惑】,如下:

运行:

最后运行看一下效果:

那ios上运行效果是否也一样呢?这里开一个ios模拟器瞅一下:

嗯,还不错,只不过我电脑有点卡,录屏更卡,所以可以自行真机运行看一下性能怎么样~~

总结:

最后纵观一下对于这次首页功能的编写,发现整体的编写思路都是从局部的widget,再到全局的widget,一点点进行构建,比如拿商品推荐组件来说,它由标题和列表组成,于是乎将整体拆成了2个widget来进行实现:

这样实现起来代码可读性也比较强,而不要将所有的实现全塞到这块:

先学到这,下次继续~~

关注个人公众号,获得实时推送

这篇关于Flutter项目实战之女装商城------添加轮播图、分类导航、商品推荐、广告位处理、底部商品的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/771645

相关文章

网页解析 lxml 库--实战

lxml库使用流程 lxml 是 Python 的第三方解析库,完全使用 Python 语言编写,它对 XPath表达式提供了良好的支 持,因此能够了高效地解析 HTML/XML 文档。本节讲解如何通过 lxml 库解析 HTML 文档。 pip install lxml lxm| 库提供了一个 etree 模块,该模块专门用来解析 HTML/XML 文档,下面来介绍一下 lxml 库

不懂推荐算法也能设计推荐系统

本文以商业化应用推荐为例,告诉我们不懂推荐算法的产品,也能从产品侧出发, 设计出一款不错的推荐系统。 相信很多新手产品,看到算法二字,多是懵圈的。 什么排序算法、最短路径等都是相对传统的算法(注:传统是指科班出身的产品都会接触过)。但对于推荐算法,多数产品对着网上搜到的资源,都会无从下手。特别当某些推荐算法 和 “AI”扯上关系后,更是加大了理解的难度。 但,不了解推荐算法,就无法做推荐系

这15个Vue指令,让你的项目开发爽到爆

1. V-Hotkey 仓库地址: github.com/Dafrok/v-ho… Demo: 戳这里 https://dafrok.github.io/v-hotkey 安装: npm install --save v-hotkey 这个指令可以给组件绑定一个或多个快捷键。你想要通过按下 Escape 键后隐藏某个组件,按住 Control 和回车键再显示它吗?小菜一碟: <template

基于人工智能的图像分类系统

目录 引言项目背景环境准备 硬件要求软件安装与配置系统设计 系统架构关键技术代码示例 数据预处理模型训练模型预测应用场景结论 1. 引言 图像分类是计算机视觉中的一个重要任务,目标是自动识别图像中的对象类别。通过卷积神经网络(CNN)等深度学习技术,我们可以构建高效的图像分类系统,广泛应用于自动驾驶、医疗影像诊断、监控分析等领域。本文将介绍如何构建一个基于人工智能的图像分类系统,包括环境

无人叉车3d激光slam多房间建图定位异常处理方案-墙体画线地图切分方案

墙体画线地图切分方案 针对问题:墙体两侧特征混淆误匹配,导致建图和定位偏差,表现为过门跳变、外月台走歪等 ·解决思路:预期的根治方案IGICP需要较长时间完成上线,先使用切分地图的工程化方案,即墙体两侧切分为不同地图,在某一侧只使用该侧地图进行定位 方案思路 切分原理:切分地图基于关键帧位置,而非点云。 理论基础:光照是直线的,一帧点云必定只能照射到墙的一侧,无法同时照到两侧实践考虑:关

如何用Docker运行Django项目

本章教程,介绍如何用Docker创建一个Django,并运行能够访问。 一、拉取镜像 这里我们使用python3.11版本的docker镜像 docker pull python:3.11 二、运行容器 这里我们将容器内部的8080端口,映射到宿主机的80端口上。 docker run -itd --name python311 -p

认识、理解、分类——acm之搜索

普通搜索方法有两种:1、广度优先搜索;2、深度优先搜索; 更多搜索方法: 3、双向广度优先搜索; 4、启发式搜索(包括A*算法等); 搜索通常会用到的知识点:状态压缩(位压缩,利用hash思想压缩)。

性能分析之MySQL索引实战案例

文章目录 一、前言二、准备三、MySQL索引优化四、MySQL 索引知识回顾五、总结 一、前言 在上一讲性能工具之 JProfiler 简单登录案例分析实战中已经发现SQL没有建立索引问题,本文将一起从代码层去分析为什么没有建立索引? 开源ERP项目地址:https://gitee.com/jishenghua/JSH_ERP 二、准备 打开IDEA找到登录请求资源路径位置

深入探索协同过滤:从原理到推荐模块案例

文章目录 前言一、协同过滤1. 基于用户的协同过滤(UserCF)2. 基于物品的协同过滤(ItemCF)3. 相似度计算方法 二、相似度计算方法1. 欧氏距离2. 皮尔逊相关系数3. 杰卡德相似系数4. 余弦相似度 三、推荐模块案例1.基于文章的协同过滤推荐功能2.基于用户的协同过滤推荐功能 前言     在信息过载的时代,推荐系统成为连接用户与内容的桥梁。本文聚焦于

C#实战|大乐透选号器[6]:实现实时显示已选择的红蓝球数量

哈喽,你好啊,我是雷工。 关于大乐透选号器在前面已经记录了5篇笔记,这是第6篇; 接下来实现实时显示当前选中红球数量,蓝球数量; 以下为练习笔记。 01 效果演示 当选择和取消选择红球或蓝球时,在对应的位置显示实时已选择的红球、蓝球的数量; 02 标签名称 分别设置Label标签名称为:lblRedCount、lblBlueCount