Flutter系列(十一)实现商城首页和商品详情页

这篇具有很好参考价值的文章主要介绍了Flutter系列(十一)实现商城首页和商品详情页。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

基础工程:

Flutter系列(四)底部导航+顶部导航+图文列表完整代码_摸金青年v的博客-CSDN博客

一、前言

        本文用flutter实现商城首页商品详情页,效果如下图:

Flutter,商城首页,商品详情页,瀑布流插件,动画特效,底部固定栏             Flutter,商城首页,商品详情页,瀑布流插件,动画特效,底部固定栏

二、使用的组件

MasonryGridView.count   瀑布流插件,组合Expanded可以添加固定在底部的按钮组

三、完整代码

 3.1 商城首页

1)瀑布流官方插件文档:flutter_staggered_grid_view | Flutter Package (pub.dev)

pubspec.yaml   添加依赖:   

dependencies:
  flutter:
    sdk: flutter
  # 瀑布流插件
  flutter_staggered_grid_view: ^0.6.2
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';

2)页面跳转动画特效:动画特效工具类   animationUtile.dart    

参考文章:Flutter系列(九)ListView实现新闻列表和正文布局_摸金青年v的博客-CSDN博客

3)顶部搜索框

参考文章:Flutter系列(八)搜索框详解_flutter 搜索框_摸金青年v的博客-CSDN博客

商城首页  shop.dart

import 'package:flutter/material.dart';
import 'package:flutter_play/search.dart';
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
import 'package:flutter_play/animationUtile.dart';
import 'package:flutter_play/skuDetail.dart';


/*商城页*/
class ShopPage extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: const Color(0xFFFBFBFB), //顶部背景色
        title: SearchAppBar(),  // 顶部搜素框(自定义组件)
      ),
      body: Column(
        children: [
          Container(
            margin: const EdgeInsets.all(8),
            width: 500,
            height: 180,
            child: Image.network('https://img-blog.yssmx.com/63efe7acbac74e7ebce85e3801f948e3.jpeg'
                , fit: BoxFit.fill, width: 500, height: 200), //可放轮播图 商品类别 筛选之类的
          ),
          Expanded(
            child: MasonryGridView.count( //瀑布流插件
              itemCount: listData.length, //条目个数:获取数据的个数
              scrollDirection: Axis.vertical, //默认主轴是垂直方向
              crossAxisCount: 2, //交叉轴(水平方向)列数
              mainAxisSpacing: 4, //主轴:垂直方向间距
              crossAxisSpacing: 4, //交叉轴:水平方向间距
              itemBuilder: _showSku,
              // shrinkWrap:true, //含义是真空压缩组件,对性能损耗很大,不建议使用
            ), //Expanded 解决GridView嵌套在Column中不兼容的问题
          )
        ]
      ),
    );
  }

  //sku列表展示
  Widget _showSku(context, index) {
    return Container(
      padding: const EdgeInsets.fromLTRB(8, 5, 8, 5),
      decoration: BoxDecoration(
          border: Border.all(
            color: const Color.fromRGBO(233, 233, 233, 0.9), //边框颜色
            width: 2, //边框宽度
        ), //边框
      ),
      child: GestureDetector(
        onTap: () {
          Navigator.of(context).push(showPageFromRight(SkuDetailPage()));  //点击跳转到商品详情页
        },
        child: Column(
          children: [
            Image.network(listData[index]["imageUrl"],
                height: 150,
                width: double.infinity, //宽度撑满
                fit: BoxFit.cover //图片撑满父容器,截断
            ),
            Column(
                mainAxisAlignment: MainAxisAlignment.spaceAround, //沿着主轴方向(垂直方向)间距等分
                crossAxisAlignment: CrossAxisAlignment.start, //水平方向左侧对齐
                children: [
                  Text(listData[index]["title"], style: const TextStyle(fontSize: 13, fontWeight: FontWeight.w600),
                      maxLines: 2, //最大显示两行
                      overflow: TextOverflow.ellipsis  //超出部分省略号
                  ),
                  Row(
                    mainAxisAlignment: MainAxisAlignment.spaceBetween, //水平方向两端对齐
                    children: [
                      Row(
                        children: [
                          const Text(' ¥', style: TextStyle(color: Colors.redAccent, fontSize: 12, fontWeight: FontWeight.w600)),
                          Text(listData[index]["price"], style: const TextStyle(color: Colors.redAccent, fontSize: 12, fontWeight: FontWeight.w600)),
                        ],
                      ),
                      Row(
                        children: [
                          const Text('销量 ', style: TextStyle(color: Colors.grey, fontSize: 12, fontWeight: FontWeight.w600)),
                          Text(listData[index]["saleNum"], style: const TextStyle(color: Colors.grey, fontSize: 12, fontWeight: FontWeight.w600)), //数据类型要准确,Text必须是String
                        ],
                      ),
                    ],
                  ),
                ]
            )
          ],
        ),
      )
    );
  }

  //数据
  List listData = [
    {
      "title": "OPPO K9x 8GB+128GB 银紫超梦 天玑810 5000mAh长续航 33W快充 90Hz电竞",
      "price": "2788",
      "imageUrl": "https://img-blog.yssmx.com/c6dfd375abf1433fa3a42951cc186a2b.jpeg",
      "saleNum": "3000"
    },
    {
      "title": "Redmi K60 骁龙8+处理器 2K高光屏 6400万超清相机 5500mAh长续航",
      "price": "2998",
      "imageUrl": "https://img-blog.yssmx.com/c6dfd375abf1433fa3a42951cc186a2b.jpeg",
      "saleNum": "500"
    },
    {
      "title": "Apple iPhone 14 Pro (A2892) 256GB 暗紫色 支持移动联通电信5G 双卡双待手机",
      "price": "5899",
      "imageUrl": "https://img-blog.yssmx.com/c6dfd375abf1433fa3a42951cc186a2b.jpeg",
      "saleNum": "2400"
    },
    {
      "title": "三星 SAMSUNG Galaxy Z Fold4 沉浸大屏体验 PC般强大生产力 12GB+512GB",
      "price": "4677",
      "imageUrl": "https://img-blog.yssmx.com/c6dfd375abf1433fa3a42951cc186a2b.jpeg",
      "saleNum": "600"
    },
    {
      "title": "华为畅享 60X 7000mAh长续航 6.95英寸 影音大屏 256GB 曜金黑 鸿蒙智能手机",
      "price": "3778",
      "imageUrl": "https://img-blog.yssmx.com/c6dfd375abf1433fa3a42951cc186a2b.jpeg",
      "saleNum": "900"
    },
    {
      "title": "荣耀X30 骁龙6nm疾速5G芯 66W超级快充 120Hz全视屏 全网通版",
      "price": "4999",
      "imageUrl": "https://img-blog.yssmx.com/c6dfd375abf1433fa3a42951cc186a2b.jpeg",
      "saleNum": "500"
    },
    {
      "title": "Apple iPhone 14 Pro (A2892) 256GB 暗紫色 支持移动联通电信5G 双卡双待手机",
      "price": "5899",
      "imageUrl": "https://img-blog.yssmx.com/c6dfd375abf1433fa3a42951cc186a2b.jpeg",
      "saleNum": "300"
    },
    {
      "title": "三星 SAMSUNG Galaxy Z Fold4 沉浸大屏体验 PC般强大生产力 12GB+512GB",
      "price": "4677",
      "imageUrl": "https://img-blog.yssmx.com/c6dfd375abf1433fa3a42951cc186a2b.jpeg",
      "saleNum": "100"
    }
  ];

}
3.2  商品详情页
import 'package:flutter/material.dart';
import 'package:flutter_play/animationUtile.dart';
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
import 'package:flutter_play/cart.dart';

/*商品详情页*/
class SkuDetailPage extends StatefulWidget {
  @override
  State<SkuDetailPage> createState() => _SkuDetailPage();
}

class _SkuDetailPage extends State<SkuDetailPage> {

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        foregroundColor: Colors.black, //字体颜色
        backgroundColor: const Color(0xFFFBFBFB), //顶部背景色
        title: const Row(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: [
            Text('商品', style: TextStyle(fontWeight: FontWeight.w500, fontSize: 15)),
            Text('评价', style: TextStyle(fontWeight: FontWeight.w500, fontSize: 15)),
            Text('详情', style: TextStyle(fontWeight: FontWeight.w500, fontSize: 15)),
            Text('推荐', style: TextStyle(fontWeight: FontWeight.w500, fontSize: 15)),
          ],
        ),
        actions: [
          IconButton(
            onPressed: () {},
            icon: const Icon(Icons.share),
          ),
          IconButton(
            onPressed: () {},
            icon: const Icon(Icons.more_horiz),
          ),
        ],
      ),
      body: Column(
        children: [
          Expanded(
            child: SingleChildScrollView(
              child: Column(
                children: [
                  Image.network('https://img-blog.yssmx.com/c6dfd375abf1433fa3a42951cc186a2b.jpeg', fit: BoxFit.fill, width: 500, height: 260), // 图片
                  priceInfo(), // 价格和促销
                  skuInfo(), // 商品参数
                  comment(), // 评价
                ],
              ),
            ),
          ),
          bottomFix() //底部固定栏
        ],
      )
    );
  }

  /*价格信息*/
  Container priceInfo(){
    return Container(
      width: 500,
      height: 45,
      decoration: BoxDecoration(
        color: const Color.fromARGB(50, 255, 48, 48),
        borderRadius: BorderRadius.circular(6), // 设置圆角
      ),
      margin: const EdgeInsets.all(5),
      padding: const EdgeInsets.all(5),
      child: const Column(
        mainAxisAlignment: MainAxisAlignment.spaceAround,
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Text('到手价  ¥4999', style: TextStyle(color: Colors.redAccent, fontSize: 14, fontWeight: FontWeight.w600)),
          Text('立减20 | 30天价保 | 包含运费险', style: TextStyle(color: Colors.redAccent, fontSize: 12, fontWeight: FontWeight.w400)),
        ],
      ),
    );
  }

  /*商品名称+选品+地址+时效*/
  Container skuInfo(){
    return Container(
      width: 500,
      height: 200,
      margin: const EdgeInsets.all(5),
      decoration: BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.circular(10),
      ),
      child: const Column(
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        children: [
          Text('Apple iPhone 14 Pro (A2892) 256GB 暗紫色 支持移动联通电信5G 双卡双待手机', style: TextStyle(fontSize: 14, fontWeight: FontWeight.w600)), //商品名称
          Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween, //水平方向两端对齐
              children: [
                Text('选品 ', style: TextStyle(color: Colors.grey, fontSize: 14, fontWeight: FontWeight.w400)),
                Text('已选: 暗紫色 1件 256G 0.33kg', style: TextStyle(fontSize: 14, fontWeight: FontWeight.w400)),
                Icon(Icons.arrow_forward_ios, size: 10)
              ],
          ),
          Row(
            mainAxisAlignment: MainAxisAlignment.spaceBetween, //水平方向两端对齐
            children: [
              Text('参数 ', style: TextStyle(color: Colors.grey, fontSize: 14, fontWeight: FontWeight.w400)),
              Column(
                children: [
                  Text('A15  ', style: TextStyle(fontSize: 14, fontWeight: FontWeight.w400)),
                  Text('cpu  ', style: TextStyle(color: Colors.grey, fontSize: 14, fontWeight: FontWeight.w400)),
                ],
              ),
              Column(
                children: [
                  Text('6.1英寸  ', style: TextStyle(fontSize: 14, fontWeight: FontWeight.w400)),
                  Text('尺寸  ', style: TextStyle(color: Colors.grey, fontSize: 14, fontWeight: FontWeight.w400)),
                ],
              ),
              Column(
                children: [
                  Text('OLED直屏  ', style: TextStyle(fontSize: 14, fontWeight: FontWeight.w400)),
                  Text('屏幕材质  ', style: TextStyle(color: Colors.grey, fontSize: 14, fontWeight: FontWeight.w400)),
                ],
              ),
              Icon(Icons.arrow_forward_ios, size: 10)
            ],
          ),
          Row(
            mainAxisAlignment: MainAxisAlignment.spaceBetween, //水平方向两端对齐
            children: [
              Text('配送 ', style: TextStyle(color: Colors.grey, fontSize: 14, fontWeight: FontWeight.w400)),
              Column(
                children: [
                  Text('北京 海淀区', style: TextStyle(color: Colors.grey, fontSize: 14, fontWeight: FontWeight.w400)),
                  Text('现货,预计今天(06月23日)送达', style: TextStyle(fontSize: 14, fontWeight: FontWeight.w400)),
                ],
              ),
              Icon(Icons.arrow_forward_ios, size: 10)
            ],
          )
        ],
      ),
    );
  }

  /*评价*/
  Container comment(){
    return Container(
      width: 500,
      height: 190,
      decoration: BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.circular(10), // 设置圆角
      ),
      margin: const EdgeInsets.all(10),
      padding: const EdgeInsets.only(top: 5),
      // alignment: Alignment.centerLeft,
      child: Column(
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        children: [
          const Row(
            mainAxisAlignment: MainAxisAlignment.spaceBetween, //水平方向两端对齐
            children: [
              Text('评价 (200万+)', style: TextStyle(fontSize: 14, fontWeight: FontWeight.w400)),
              Row(
                children: [
                  Text('好评度 97%', style: TextStyle(color: Colors.grey, fontSize: 12, fontWeight: FontWeight.w400)),
                  Icon(Icons.arrow_forward_ios, size: 10)
                ],
              ),
            ],
          ),
          SizedBox(height: 2),
          Row(
            children: [
              ClipOval(
                  child: Image.network('https://img-blog.yssmx.com/c6dfd375abf1433fa3a42951cc186a2b.jpeg', width: 30, height: 30, fit: BoxFit.cover),
              ), //圆型头像
              const Text(' 吴邪', style: TextStyle(color: Colors.grey, fontSize: 14, fontWeight: FontWeight.w400)),
            ],
          ),
          SizedBox(height: 2),
          const Text('外观: 小巧精致,手感不错,屏幕流畅,拍照功能强大', style: TextStyle(fontSize: 14, fontWeight: FontWeight.w400)),
          SizedBox(height: 3),
          Expanded(
            child: MasonryGridView.count(
              scrollDirection: Axis.horizontal, //水平方向
              itemCount: listData.length, //条目个数:获取数据的个数
              crossAxisCount: 1, //交叉轴(水平方向)行数
              mainAxisSpacing: 4,
              crossAxisSpacing: 4,
              itemBuilder: (context, index) {
                return Image.network(listData[index]["imageUrl"], width: 120, height: 50, fit: BoxFit.cover);
              }
            ),
          )//图片组
        ],
      ),
    );
  }

  List listData = [
    {
      "imageUrl": "https://img-blog.yssmx.com/c6dfd375abf1433fa3a42951cc186a2b.jpeg",
    },
    {
      "imageUrl": "https://img-blog.yssmx.com/c6dfd375abf1433fa3a42951cc186a2b.jpeg",
    },
    {
      "imageUrl": "https://img-blog.yssmx.com/c6dfd375abf1433fa3a42951cc186a2b.jpeg",
    },
    {
      "imageUrl": "https://img-blog.yssmx.com/c6dfd375abf1433fa3a42951cc186a2b.jpeg",
    },
    {
      "imageUrl": "https://img-blog.yssmx.com/c6dfd375abf1433fa3a42951cc186a2b.jpeg",
    }
  ];

  /*底部固定:购物车+立即购买*/
  Container bottomFix(){
    return Container(
      width: 500,
      height: 50,
      color: Colors.white,
      // alignment: Alignment.centerLeft,
      child: ButtonBar(
          children: [
            IconButton(
              color: Colors.grey,
              icon: const Icon(Icons.add_business), //店铺
              onPressed:(){},
            ),
            IconButton(
              color: Colors.grey,
              icon: const Icon(Icons.star_border_outlined), //收藏
              onPressed:(){},
            ),
            IconButton(
              color: Colors.grey,
              icon: const Icon(Icons.add_shopping_cart), //购物车
              onPressed:(){
                Navigator.of(context).push(showPageFromRight(CartPage())); //点击购物车图标,进入购物车页
              },
            ),
            TextButton  (
              style: ButtonStyle(
                  minimumSize: MaterialStateProperty.all(const Size(80, 50)),
                  foregroundColor: MaterialStateProperty.all<Color>(Colors.pinkAccent), //字体颜色
                  shape: MaterialStateProperty.all(RoundedRectangleBorder(borderRadius: BorderRadius.circular(10))), //圆角
                  side: MaterialStateProperty.all(const BorderSide(color: Colors.pinkAccent, width: 0.67)) // 边框颜色
              ),
              child: const Text('加入购物车'),
              onPressed: () {

              },
            ),
            TextButton (
              style: ButtonStyle(
                  minimumSize: MaterialStateProperty.all(const Size(80, 50)),
                  backgroundColor: MaterialStateProperty.all(Colors.pinkAccent),
                  foregroundColor: MaterialStateProperty.all<Color>(Colors.white), //字体颜色
                  shape: MaterialStateProperty.all(RoundedRectangleBorder(borderRadius: BorderRadius.circular(10))) //圆角
              ),
              child: const Text('立即购买'),
              onPressed: () {

              },
            ),
          ]
      ),
    );
  }

}

四、解决问题

4.1 商品详情页-评论模块的,图片组支持水平滑动,使用的还是瀑布流组件,需要设置参数:

1.设置了水平方向为主轴,表示滚动方向为水平

2.设置了交叉轴行数等于1,表示图片只有一行显示

MasonryGridView.count(
              scrollDirection: Axis.horizontal, //水平方向
              itemCount: listData.length, //条目个数:获取数据的个数
              crossAxisCount: 1, //交叉轴(水平方向)行数
              mainAxisSpacing: 4,
              crossAxisSpacing: 4,
              itemBuilder: (context, index) {
                return Image.network(listData[index]["imageUrl"], width: 120, height: 50, fit: BoxFit.cover);
              }
            ),

本文结束文章来源地址https://www.toymoban.com/news/detail-705025.html

到了这里,关于Flutter系列(十一)实现商城首页和商品详情页的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【拼多多API 开发系列】百亿补贴商品详情接口,代码封装

    为了进行电商平台 PDD 的API开发,首先我们需要做下面几件事情。 1)开发者注册一个账号 2)然后为每个 PDD 应用注册一个应用程序键(App Key) 。 3)下载 PDD API的SDK并掌握基本的API基础知识和调用 4)利用SDK接口和对象,传入AppKey或者必要的时候获取并传入SessionKey来进行程序

    2024年02月06日
    浏览(28)
  • 淘宝Api接口开发系列,商品详情数据,搜索商品列表数据,无货源采集上货模式,数据分析

    淘宝API接口开发涉及多个方面,包括获取商品详情数据、搜索商品列表数据、无货源采集上货模式以及数据分析等。今天给大家介绍下通过封装商品ID获取淘宝商品详情数据接口方法,支持高并发请求。下面我将分别对这些方面进行简要介绍。 1. 商品详情数据接口 商品详情数

    2024年04月16日
    浏览(55)
  • 1688商品详情API:实现商品详情自动化的关键步骤

    一、准备工作 在使用1688商品详情API之前,我们需要进行一些准备工作。 注册与登录 :首先,你需要在1688的开放平台上注册一个账号并创建一个应用。这样你就可以获得一个API密钥,这是调用API的凭证。 阅读API文档 :详细阅读1688提供的API文档,了解API的调用方式、参数要

    2024年02月03日
    浏览(37)
  • Flutter中GetX系列六--GetxController/GetView使用详情

    在实际的项目开发过程中,我们不可能把UI代码、业务逻辑都放在一起处理,这样对项目的架构、代码的可读性、后期的维护将会是致命的,好在 GetX 为我们提供了 GetxController , GetxController 主要的作用是用于UI代码与业务逻辑分离开来。 这里主要讲解使用 GetxController 动态获取

    2024年02月10日
    浏览(39)
  • HTML .CSS实现商品详情(detail)

    一、知识点 1、无序列表ul/ul 2、float浮动 (1)why浮动的作用:排版布局 (2)原理:两个盒子,默认上下排列,给第二个盒子就会浮上去(跟第一个盒子同一水平线) (3)how怎么用: (4)clear:清除浮动 3、CSS精灵图 4、详情页面用到的CSS属性: (1)、border-radius:边框圆角半径 (2)、

    2024年02月11日
    浏览(30)
  • 1688API技术解析,实现获得1688商品详情

        要实现获得1688商品详情,你需要使用1688 API。1688 API是阿里巴巴旗下的开放平台,它提供了一套丰富的接口,可以让开发者通过编程的方式获取到1688网站上的商品信息。 首先,你需要在阿里开放平台注册一个账号,并创建一个应用。然后,根据1688开放平台的文档,了解

    2024年02月11日
    浏览(35)
  • 微信小程序商品详情页(页面的实现)

    通过搜索页面传入的id,来进行操作(没有接口,都是假数据),页面如下 首先先把页面搭建起来,并进行渲染顶部导航栏已经做过现在就不发了,直接复制就好 页面信息的wxml 尾部导航栏wxml  js wxss 现在简单的小页面完成了

    2024年02月04日
    浏览(40)
  • 实现自动化获取1688商品详情数据接口经验分享

    获取电商平台商品详情数据,主要用过的是爬虫技术,过程比较曲折,最终结果是好的。我将代码都封装在1688.item_get接口中,直接调用此接口可以一步抓取。 1688商品详情页展示 传入商品ID调用item_get获取数据 响应示例  

    2024年02月07日
    浏览(33)
  • 第八章 实现商品详情数据异构及静态化

    lua操作 设计图详解 1、 普通模式,用户获得redis数据需要经过nginx, php-fpm,php框架 ,再到redis 2 、直接模式,对于部分 高并发请求, 为了提高吞吐率 , 有必要砍掉一些环节和应用来实现快速响应,如上图,这里我们将普通模式中的php-fpm和php框架砍掉了。 nginx直接从redis获

    2024年02月13日
    浏览(38)
  • 第7讲:使用ajax技术实现弹出商品详情提示功能(xml数据)

    使用ajax技术使用ajax技术实现弹出商品详情提示功能,本案例使用原生态xmlhttprequest对象,GET方法异步通讯,后台使用map保存搜索数据,查询到对应数据后,返回xml格式数据,前端使用responseXML属性返回xml格式数据,解析xml文件内容,结合JavaScript定位并显示商品详情。 特别说

    2024年02月11日
    浏览(34)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包