Flutter+开源鸿蒙实战|校园易生活Day4 闲置详情页开发+路由传参+大图轮播+收藏功能+新手避坑

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net

<!-- Schema.org 结构化数据 -->
<script type="application/ld+json">
{
  "@context":"https://schema.org",
  "@type":"BlogPosting",
  "headline":"Flutter+开源鸿蒙实战 校园易生活Day4 闲置详情页+路由传参+大图轮播+收藏功能+新手避坑",
  "author":{"@type":"Person","name":"鸿蒙跨端开发者"},
  "publisher":{"@type":"Organization","name":"CSDN开源鸿蒙跨平台社区"},
  "datePublished":"2026-05-06",
  "description":"校园易生活Day4完整开发闲置详情页面,实现路由传参接收、商品大图轮播、完整信息展示、收藏功能、联系卖家按钮,附带新手常见问题解答,适配鸿蒙多端设备",
  "keywords":"Flutter,开源鸿蒙,OpenHarmony,校园易生活,Day4,闲置详情页,路由传参,大图轮播,收藏功能"
}
</script>

在这里插入图片描述

一、前言

哈喽小伙伴们,咱们继续肝校园易生活Day4啦!🥳

回顾一下Day3,咱们搞定了闲置市场的列表页——搭了网格布局、封装了商品卡片、用GetX管了数据,还做了下拉刷新,最后给卡片加了点击跳转的预留逻辑。

今天咱们就把这个“坑”填上,完整开发闲置商品详情页!这一步特别关键,毕竟用户点进商品,肯定要看到完整信息,也是毕设里“页面交互”的重点得分项,咱们一步步来,不着急。

全程我尽量说人话,不搞那些生硬的技术术语,每段代码前都用大白话讲清楚“这行代码是干嘛的”,新手也能看懂;代码只放最核心的5-6行,不冗余、不堆砌;还会预判你们写代码时,大概率会踩的坑,口语化分点讲明白原因和解决办法,保证你们跟着写,能一次跑通,不报错、不卡壳。

另外,所有功能都适配鸿蒙手机、平板的实景运行效果,写完就能在真机上看到完整效果,成就感拉满!

今日咱们要搞定的核心事儿(通俗版):

  1. 新建详情页,搭好基础架子(顶部返回、主体内容区);
  2. 接收Day3跳转时带过来的商品数据(比如标题、价格、图片);
  3. 做商品大图轮播,支持手动滑、自动滑,跟平时刷APP一样;
  4. 做收藏功能,点击星星切换收藏/取消,还会有提示;
  5. 加“联系卖家”按钮,先做个提示,后续再搞真正的拨号;
  6. 优化页面交互,比如滑动不溢出、按钮不遮挡;
  7. 适配鸿蒙手机、平板,保证布局不歪、不拉伸;
  8. 汇总新手最容易踩的坑,一个个讲透怎么解决。

二、今日依赖库说明(省事儿版)

不用新增任何库!不用改pubspec.yaml!不用执行flutter pub get!
直接用前3天咱们装过的所有库:flutter_screenutil、getx、flutter_easy_refresh、fluttertoast、connectivity_plus、flutter_swiper_null_safe,直接上手写就行,省得多余操作。

三、版块1:新建闲置详情页面(基础骨架,先搭个壳)

文字讲解(大白话)

咱们先给详情页搭个最基础的架子,跟之前所有页面保持一致,这样看起来整齐,后期维护也方便。顶部弄个导航栏,加个返回按钮(点一下就能回到列表页),主体部分用滚动组件包起来(防止内容太多看不到),里面先空着,后续再把轮播、商品信息、按钮填进去,适配鸿蒙多端,不会一上来就乱布局。

class IdleDetailPage extends StatelessWidget {
  const IdleDetailPage({super.key});

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("商品详情"),
        // 左上角返回按钮,点一下回到上一页
        leading: IconButton(icon: const Icon(Icons.backspace), onPressed: () => Get.back()),
      ),
      // 滚动组件,防止内容太多溢出看不到
      body: SingleChildScrollView(
        child: Column(children: const [/* 后面把轮播、信息、按钮填这 */]),
      ),
    );
  }
}

四、版块2:GetX路由传参接收(核心!拿到商品数据)

文字讲解(大白话)

Day3咱们点击商品卡片时,已经把商品的所有数据(标题、价格、图片)带过来了,这一步就是“接住”这些数据。不用写复杂的代码,一行Get.arguments就能拿到,拿到之后,就能把这些数据显示在详情页上,比如把标题显示在页面里、把图片显示在轮播图里。

class IdleDetailPage extends StatelessWidget {
  const IdleDetailPage({super.key});

  
  Widget build(BuildContext context) {
    // 关键代码:接住Day3跳转时带过来的商品数据
    final IdleModel model = Get.arguments;
    return Scaffold(
      appBar: AppBar(title: const Text("商品详情")),
      body: SingleChildScrollView(child: Column(children: [/* 用拿到的数据渲染页面 */])),
    );
  }
}

五、版块3:集成商品大图轮播(多图切换,跟平时刷APP一样)

在这里插入图片描述

文字讲解(大白话)

详情页最顶部,肯定要放商品的大图,而且很多商品不止一张图,所以咱们做个轮播。这里先模拟3张图(实际后期对接接口,就能显示真实图片),支持自动轮播、手动滑动,底部加个小圆点指示器,告诉咱们当前在看第几张图,适配鸿蒙手机、平板,图不会拉伸、不会溢出。

Widget buildImageSwiper(IdleModel model) {
  // 模拟商品多图(比如商品主图+细节图,后期换接口数据就行)
  final List<String> imgList = [model.img, "assets/images/idle2.jpg", "assets/images/idle3.jpg"];
  return Swiper(
    itemCount: imgList.length, // 轮播图数量,跟图片数组长度一致
    autoplay: true, // 自动轮播,不用手动滑
    itemBuilder: (ctx, index) => Image.asset(imgList[index], fit: BoxFit.cover),
    pagination: const SwiperPagination(), // 底部小圆点指示器
  );
}

六、版块4:商品完整信息布局(把商品详情显示出来)

文字讲解(大白话)

轮播图下面,就是商品的详细信息了——标题、价格、描述、发布时间,按从上到下的顺序排,看着清晰。价格弄成红色,显眼;描述和发布时间弄成灰色,区分主次;所有文字大小、间距都用适配单位,保证在手机上不挤、在平板上不空旷,鸿蒙多端都好看。

Widget buildIdleInfo(IdleModel model) {
  return Padding(
    padding: EdgeInsets.all(15.w), // 四周留空白,不挤
    child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
      Text(model.title, style: TextStyle(fontSize: 16.sp, fontWeight: FontWeight.w600)),
      SizedBox(height: 10.h), // 留一点间距,不拥挤
      Text(${model.price}", style: TextStyle(color: Colors.redAccent, fontSize: 18.sp)),
      SizedBox(height: 10.h),
      Text("商品描述:${model.desc}", style: TextStyle(fontSize: 14.sp, color: Colors.grey[600])),
      Text("发布时间:2026-05-06", style: TextStyle(fontSize: 12.sp, color: Colors.grey)),
    ]),
  );
}

七、版块5:开发收藏功能(点击星星切换状态,有提示)

文字讲解(大白话)

收藏功能很简单,就是一个星星图标,点击一下变成黄色(收藏成功),再点击一下变成灰色(取消收藏),同时弹出提示,告诉用户操作成功。咱们用GetX的响应式变量管理状态,不用手动刷新页面,点击之后自动切换,适配鸿蒙所有设备,交互很流畅。

class IdleDetailController extends GetxController {
  // 收藏状态:默认未收藏(false),obs表示响应式,变化时页面自动刷新
  final RxBool isCollected = false.obs;

  // 点击收藏/取消收藏的方法
  void toggleCollect() {
    isCollected.value = !isCollected.value; // 切换状态(true变false,false变true)
    // 弹出提示,告诉用户操作结果
    ToastUtil.show(isCollected.value ? "收藏成功啦~" : "已取消收藏");
  }
}

八、版块6:联系卖家按钮(先做提示,后续搞拨号)

文字讲解(大白话)

详情页底部加一个“联系卖家”按钮,颜色用咱们的主题色,圆角样式,看着美观。现在先做个点击提示(告诉用户正在联系卖家),等Day5咱们集成拨号库,就能实现真正的拨号功能,点击直接打给卖家。按钮放在底部,适配鸿蒙手机的底部安全区,不会被遮挡。

Widget buildContactBtn() {
  return Padding(
    padding: EdgeInsets.all(15.w),
    child: ElevatedButton(
      onPressed: () {
        ToastUtil.show("正在联系卖家,稍等哦~");
        // 后续Day5搞真正拨号:UrlLauncher.launchUrl(Uri.parse("tel:13800138000"));
      },
      child: const Text("联系卖家"),
    ),
  );
}

九、版块7:整合详情页所有组件(拼起来,完整可用)

文字讲解(大白话)

现在咱们把上面写的所有组件——大图轮播、商品信息、收藏按钮、联系卖家按钮,全部拼到详情页里,用Column纵向排好,外层还是用滚动组件包着,防止内容太多看不到。这样一来,一个完整的详情页就做好了,点击卡片跳转过来,就能看到所有内容,交互也流畅。

class IdleDetailPage extends StatelessWidget {
  // 先拿到商品数据
  final IdleModel model = Get.arguments;
  // 初始化收藏控制器
  final IdleDetailController ctrl = Get.put(IdleDetailController());

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text("商品详情"), leading: IconButton(icon: const Icon(Icons.backspace), onPressed: () => Get.back())),
      body: SingleChildScrollView(
        child: Column(children: [
          buildImageSwiper(model), // 大图轮播
          buildIdleInfo(model),    // 商品信息
          // 收藏按钮,根据状态切换颜色
          Obx(() => IconButton(icon: Icon(Icons.star, color: ctrl.isCollected.value ? Colors.yellow : Colors.grey), onPressed: () => ctrl.toggleCollect())),
          buildContactBtn(),       // 联系卖家按钮
        ]),
      ),
    );
  }
}

十、版块8:鸿蒙多端适配(实景运行效果,肉眼可见)

跟大家说下实景适配效果,你们写完就能在真机上看到:

  1. 手机端:整体布局紧凑,大图轮播刚好占满手机宽度,文字、按钮大小适中,底部按钮不会被遮挡,滑动流畅;
  2. 平板端:自动加宽轮播图,商品信息区域留更多空白,文字、按钮按比例放大,看着不拥挤、不空旷,布局很舒展;
  3. 小细节:不管是手机还是平板,所有间距、尺寸都是用的适配单位,轮播图不会拉伸、文字不会重叠,鸿蒙开发板运行也不会报错;
  4. 交互上:轮播切换不卡顿,点击收藏、联系按钮,反馈很及时,符合咱们平时用鸿蒙手机的习惯。

十一、版块9:新手开发常见问题(口语化,逐个讲透,避坑!)

我知道你们写代码的时候,肯定会遇到各种小问题,我把最常见的6个坑,一个个讲明白,你们对照着排查,保证能解决!

问题1:接收不到路由传参,报错“null”(最常见)

解答:就两个原因,很好排查!
① Day3跳转的时候,没带数据——回去检查一下,是不是写了Get.toNamed(“/idleDetail”, arguments: model),有没有漏写arguments;
② 详情页接收顺序错了——一定要先写final IdleModel model = Get.arguments; 再渲染页面,不能把接收代码写在后面。

问题2:大图轮播只显示一张图,切换不了

解答:大概率是轮播图的itemCount设错了!比如你有3张图,itemCount就得设成imgList.length(跟图片数组长度一致),不能写死1;另外检查一下,是不是漏写了SwiperPagination(底部小圆点),没写也可能切换不了。

问题3:收藏按钮点击没反应,状态不切换

解答:三个排查点,逐个看:
① 没给收藏按钮套Obx——GetX监听不到状态变化,按钮就不会变颜色,一定要用Obx(() => IconButton(…));
② 没初始化控制器——忘了写final IdleDetailController ctrl = Get.put(IdleDetailController()); 控制器没启动,点击当然没反应;
③ 没调用toggleCollect方法——onPressed里面一定要写ctrl.toggleCollect(),不能空着。

问题4:页面内容太多,底部按钮被遮挡、看不到

解答:太简单了!就是没给页面外层套SingleChildScrollView,内容超出屏幕高度,就会被挡住。只要把Column放在SingleChildScrollView里面,就能上下滑动,所有内容都能看到,不会被遮挡。

问题5:联系卖家按钮点击没反应,Toast不弹出

解答:排查两点:
① 按钮被其他组件遮挡了——比如padding设太大,把按钮挤到屏幕外面了,调整一下padding大小;
② 没写Toast提示——onPressed里面一定要加ToastUtil.show(…),另外确认一下,fluttertoast库是不是正常集成了,没有版本冲突。

问题6:详情页在平板上布局错乱、文字挤在一起

解答:新手最容易犯的错——用了固定数字!比如把文字大小写成16,间距写成10,平板分辨率大,固定数字就会显得很小、很挤。把所有固定数值,全部改成.w .h .sp适配单位,框架会自动适配平板尺寸,布局就舒展了。

十二、Day4 开发总结(通俗版,不搞虚的)

今天咱们算是把闲置模块的“闭环”搞定了,总结一下咱们今天干的事儿:

  1. 完整开发了闲置详情页,从基础架子到所有组件,拼起来就能用;
  2. 学会了用GetX接收路由传参,不用复杂代码,就能拿到页面间的数据;
  3. 做了大图轮播,支持自动、手动切换,适配鸿蒙多端,看着很专业;
  4. 搞定了收藏功能,点击切换状态,还有提示反馈,交互很友好;
  5. 加了联系卖家按钮,预留了拨号逻辑,后续完善一下就能用;
  6. 适配了鸿蒙手机、平板,布局不歪、不拉伸,实景运行效果很好;
  7. 解决了新手最容易踩的6个坑,以后再遇到,不用慌,直接对照排查;
  8. 完成了“闲置列表→详情页”的完整流程,毕设的核心模块又完善了一步。
    在这里插入图片描述

十三、下期Day5预告(提前剧透)

Day5咱们继续往下搞,重点做这几件事:

  1. 完善联系卖家功能,集成拨号库,点击按钮真正能打电话;
  2. 开发闲置发布页面的基础布局,让用户能发布自己的二手商品;
  3. 加图片选择功能,支持从相册/相机选图,复用之前的资源;
  4. 封装统一的输入框,发布商品时填写标题、价格、描述;
  5. 完善收藏功能,用缓存保存收藏状态,退出APP再进来,收藏不会消失。
Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐