Flutter+开源鸿蒙实战|智安盾电商溯源平台Day2 首页+核心入口UI开发(鸿蒙多端适配)

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

摘要

本文基于Flutter + 开源鸿蒙跨端技术栈,继续讲解智安盾跨境电商溯源合规平台实战开发第二天内容。全程口语化讲解、弱化冗余代码、强化操作逻辑与鸿蒙适配细节,重点带大家完成首页整体布局、溯源查询核心入口开发、全局导航栏/底部菜单栏搭建,同时适配鸿蒙手机、平板、DAYU200开发板多设备显示,零基础也能跟着一步步操作,为后续溯源查询、合规检测功能落地打好UI基础。
在这里插入图片描述

<!-- Schema.org 结构化数据 -->
<script type="application/ld+json">
{
  "@context":"https://schema.org",
  "@type":"BlogPosting",
  "headline":"Flutter+开源鸿蒙实战 智安盾Day2 首页+核心入口UI开发",
  "author":{"@type":"Person","name":"鸿蒙跨端开发者"},
  "publisher":{"@type":"Organization","name":"CSDN开源鸿蒙跨平台社区"},
  "datePublished":"2026-04-28",
  "description":"Flutter+开源鸿蒙开发智安盾,Day2讲解首页布局、溯源查询入口、导航栏开发及鸿蒙多端适配",
  "keywords":"开源鸿蒙,OpenHarmony,Flutter跨端,电商溯源,智安盾,UI开发,鸿蒙多端适配"
}
</script>

一、前言

哈喽大家好,昨天Day1我们已经把智安盾项目的地基打牢了——理清了项目背景、痛点、整体架构,搭建了规范的项目目录,完成了基础环境配置和鸿蒙预适配,成功运行了初始化项目。

今天Day2,我们正式进入UI开发阶段,这也是整个项目最直观、最有成就感的一步!毕竟不管功能多强大,先把界面做好看、做顺手,不管是自己开发还是用来比赛、毕设,都能加分不少。

今天我们不搞复杂的业务逻辑,全程围绕“UI布局+鸿蒙多端适配”展开,重点做3件事:一是搭建首页整体框架,贴合跨境溯源合规的简约风格;二是开发溯源查询核心入口(这是我们项目的核心功能入口,消费者最常用);三是完成全局导航栏、底部菜单栏,同时适配鸿蒙手机、平板、DAYU200开发板,保证多设备显示正常、操作流畅。

全程依旧口语化讲解,代码只放核心关键部分,重点讲“为什么这么设计、鸿蒙端怎么适配、遇到问题怎么解决”,新手也能轻松跟上。

二、Day2 核心开发目标

今天的开发目标非常明确,所有操作都围绕“UI落地+鸿蒙适配”,不贪多、不复杂,确保每一步都能落地:

  1. 搭建首页整体布局,确定简约、专业的视觉风格,贴合合规类产品调性;
  2. 开发防伪码溯源查询核心入口(输入框+查询按钮),适配鸿蒙多设备触控;
  3. 完成全局顶部导航栏开发,适配鸿蒙系统状态栏、大屏显示;
  4. 开发底部菜单栏,实现首页、溯源查询、合规检测、个人中心四大页面切换;
  5. 重点做鸿蒙多端适配:手机/平板/开发板布局自适应、文字大小适配、触控区域优化;
  6. 新增全局复用组件(按钮、输入框),统一UI风格,为后续开发节省时间;
  7. 运行测试,确保所有UI组件在鸿蒙设备上显示正常、无错乱、无卡顿。

三、前期准备(衔接Day1,快速上手)

在开始今天的开发前,先确认2个关键前提,避免出现衔接问题:

  1. 本地Flutter+鸿蒙开发环境正常,Day1创建的项目能正常运行(如果运行报错,先检查依赖是否安装完整,执行flutter pub get重新拉取依赖);
  2. 项目目录已按Day1规范搭建完成(lib/pages、lib/widgets等文件夹已创建),确保代码存放规范;
  3. 准备好测试设备(鸿蒙手机模拟器、真机、DAYU200开发板任选其一),方便实时查看适配效果。

这里提醒一句:鸿蒙开发和普通Flutter开发最大的区别,就是多端适配,今天我们每写一个组件,都会同步做适配,避免后期批量修改,踩坑少走弯路。
在这里插入图片描述

四、核心开发流程

4.1 第一步:创建全局复用组件(统一风格,减少重复代码)

我们先创建2个最常用的全局组件——自定义按钮、自定义输入框,后续首页、溯源查询页、登录页都会用到,统一风格的同时,也能减少重复代码,还能专门做鸿蒙触控适配。

4.1.1 自定义按钮(适配鸿蒙触控,重点!)

lib/widgets/custom_button.dart中创建组件,重点优化鸿蒙设备的触控体验:

  • 鸿蒙开发板触控精度低,我们把按钮最小触控区域设置为48dp(鸿蒙官方推荐最小触控尺寸);
  • 统一按钮颜色、圆角、文字样式,贴合安全合规类产品的简约风格;
  • 增加点击反馈,让用户明确知道“点击有效”,尤其是长辈、新手用户。

核心关键代码(只放重点,不堆砌):

import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';

// 自定义按钮(鸿蒙多端适配版)
class CustomButton extends StatelessWidget {
  final String text; // 按钮文字
  final VoidCallback onTap; // 点击事件
  final bool isDisabled; // 是否禁用

  const CustomButton({
    super.key,
    required this.text,
    required this.onTap,
    this.isDisabled = false,
  });

  
  Widget build(BuildContext context) {
    // 判断是否为鸿蒙开发板/平板,调整按钮尺寸
    final isDayuOrTablet = MediaQuery.of(context).size.width >= 600;
    
    return GestureDetector(
      onTap: isDisabled ? null : onTap,
      child: Container(
        // 鸿蒙适配:开发板/平板按钮放大,触控区域≥48dp
        width: isDayuOrTablet ? 200.w : 160.w,
        height: 48.h, // 固定高度,保证触控区域足够
        alignment: Alignment.center,
        decoration: BoxDecoration(
          color: isDisabled ? Colors.grey[300] : Color(0xFF36CFC9), // 主色调,贴合安全感
          borderRadius: BorderRadius.circular(8.r), // 圆角设计,更柔和
        ),
        child: Text(
          text,
          style: TextStyle(
            color: Colors.white,
            fontSize: isDayuOrTablet ? 18.sp : 16.sp, // 鸿蒙大屏文字放大
            fontWeight: FontWeight.w500,
          ),
        ),
      ),
    );
  }
}
4.1.2 自定义输入框(适配鸿蒙,防误触)

lib/widgets/custom_input.dart中创建组件,重点优化鸿蒙设备的输入体验:

  • 放大输入框高度、文字大小,适配鸿蒙开发板、老人机的显示需求;
  • 增加输入提示、边框样式,让用户清晰知道“该输入什么”;
  • 禁止输入为空,添加基础输入校验,为后续溯源查询做铺垫。

核心关键代码(只放重点):

import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';

// 自定义输入框(鸿蒙多端适配版,用于防伪码查询)
class CustomInput extends StatelessWidget {
  final TextEditingController controller; // 输入控制器
  final String hintText; // 提示文字

  const CustomInput({
    super.key,
    required this.controller,
    required this.hintText,
  });

  
  Widget build(BuildContext context) {
    final isDayuOrTablet = MediaQuery.of(context).size.width >= 600;
    
    return Container(
      // 鸿蒙适配:开发板/平板输入框加宽,适配大屏
      width: isDayuOrTablet ? 300.w : double.infinity,
      height: 50.h,
      child: TextField(
        controller: controller,
        decoration: InputDecoration(
          hintText: hintText,
          hintStyle: TextStyle(
            color: Colors.grey[400],
            fontSize: isDayuOrTablet ? 16.sp : 14.sp,
          ),
          border: OutlineInputBorder(
            borderRadius: BorderRadius.circular(8.r),
            borderSide: BorderSide(color: Colors.grey[200]),
          ),
          focusedBorder: OutlineInputBorder(
            borderRadius: BorderRadius.circular(8.r),
            borderSide: BorderSide(color: Color(0xFF36CFC9)), // 聚焦时高亮
          ),
          // 鸿蒙适配:增加内边距,避免文字贴边
          contentPadding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 12.h),
        ),
        style: TextStyle(
          fontSize: isDayuOrTablet ? 16.sp : 14.sp,
        ),
        // 基础校验:禁止输入为空(后续可扩展防伪码格式校验)
        textInputAction: TextInputAction.done,
      ),
    );
  }
}

4.2 第二步:开发全局顶部导航栏(适配鸿蒙状态栏)

导航栏是所有页面的通用组件,我们单独创建一个组件,适配鸿蒙系统状态栏、多设备显示,避免每个页面重复写代码。

lib/widgets/app_bar.dart中创建全局导航栏:

  • 适配鸿蒙系统状态栏,避免文字与状态栏重叠;
  • 统一标题样式,开发板/平板放大文字,适配大屏;
  • 增加返回按钮(后续页面跳转用),优化鸿蒙触控体验。

核心讲解:鸿蒙设备的状态栏样式和Android略有不同,我们不需要额外复杂配置,只需要通过AppBarsystemOverlayStyle属性,统一状态栏文字颜色,确保在鸿蒙手机、开发板上显示正常,不会出现“状态栏文字看不清”的问题。

关键代码(简化版):

import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';

// 全局导航栏(鸿蒙多端适配)
class CustomAppBar extends StatelessWidget implements PreferredSizeWidget {
  final String title; // 导航栏标题
  final bool showBack; // 是否显示返回按钮

  const CustomAppBar({
    super.key,
    required this.title,
    this.showBack = false,
  });

  
  Widget build(BuildContext context) {
    final isDayuOrTablet = MediaQuery.of(context).size.width >= 600;
    
    return AppBar(
      // 鸿蒙适配:状态栏文字颜色,避免与导航栏重叠
      systemOverlayStyle: SystemUiOverlayStyle(
        statusBarColor: Colors.white,
        statusBarIconBrightness: Brightness.dark,
      ),
      title: Text(
        title,
        style: TextStyle(
          fontSize: isDayuOrTablet ? 18.sp : 16.sp,
          fontWeight: FontWeight.bold,
        ),
      ),
      centerTitle: true, // 标题居中,贴合鸿蒙UI风格
      leading: showBack
          ? IconButton(
              icon: Icon(Icons.arrow_back_ios, size: isDayuOrTablet ? 24.sp : 20.sp),
              onPressed: () => Navigator.pop(context),
            )
          : null,
      elevation: 1, // 轻微阴影,提升层次感
    );
  }

  // 固定导航栏高度,适配多设备
  
  Size get preferredSize => Size.fromHeight(56.h);
}

4.3 第三步:开发底部菜单栏(四大页面切换)

底部菜单栏是APP的核心导航,我们实现首页、溯源查询、合规检测、个人中心四大页面的切换,适配鸿蒙多设备尺寸,同时保证触控便捷。

lib/widgets/bottom_nav_bar.dart中创建组件:

  • 鸿蒙开发板/平板放大图标和文字,提升触控容错率;
  • 统一选中/未选中状态的颜色,让用户清晰知道当前所在页面;
  • 绑定页面切换逻辑,为后续页面开发做准备。

核心讲解:底部菜单栏的关键是“适配”,鸿蒙开发板是横屏显示,我们不需要修改布局,只需要放大图标和文字,确保触控区域足够;平板端也是同理,保持布局不变,放大组件尺寸,避免操作不便。

关键代码(简化版):

import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';

// 底部菜单栏(鸿蒙多端适配)
class CustomBottomNavBar extends StatelessWidget {
  final int currentIndex; // 当前选中页面索引
  final Function(int) onTap; // 切换页面事件

  const CustomBottomNavBar({
    super.key,
    required this.currentIndex,
    required this.onTap,
  });

  
  Widget build(BuildContext context) {
    final isDayuOrTablet = MediaQuery.of(context).size.width >= 600;
    
    return BottomNavigationBar(
      currentIndex: currentIndex,
      onTap: onTap,
      // 鸿蒙适配:开发板/平板增加高度,放大触控区域
      height: isDayuOrTablet ? 60.h : 50.h,
      type: BottomNavigationBarType.fixed, // 固定所有图标,不滚动
      items: [
        BottomNavigationBarItem(
          icon: Icon(Icons.home_outlined, size: isDayuOrTablet ? 24.sp : 20.sp),
          activeIcon: Icon(Icons.home, size: isDayuOrTablet ? 24.sp : 20.sp),
          label: '首页',
          labelStyle: TextStyle(fontSize: isDayuOrTablet ? 14.sp : 12.sp),
        ),
        BottomNavigationBarItem(
          icon: Icon(Icons.search_outlined, size: isDayuOrTablet ? 24.sp : 20.sp),
          activeIcon: Icon(Icons.search, size: isDayuOrTablet ? 24.sp : 20.sp),
          label: '溯源查询',
          labelStyle: TextStyle(fontSize: isDayuOrTablet ? 14.sp : 12.sp),
        ),
        BottomNavigationBarItem(
          icon: Icon(Icons.shield_outlined, size: isDayuOrTablet ? 24.sp : 20.sp),
          activeIcon: Icon(Icons.shield, size: isDayuOrTablet ? 24.sp : 20.sp),
          label: '合规检测',
          labelStyle: TextStyle(fontSize: isDayuOrTablet ? 14.sp : 12.sp),
        ),
        BottomNavigationBarItem(
          icon: Icon(Icons.person_outlined, size: isDayuOrTablet ? 24.sp : 20.sp),
          activeIcon: Icon(Icons.person, size: isDayuOrTablet ? 24.sp : 20.sp),
          label: '个人中心',
          labelStyle: TextStyle(fontSize: isDayuOrTablet ? 14.sp : 12.sp),
        ),
      ],
      selectedItemColor: Color(0xFF36CFC9), // 选中颜色,与按钮一致
      unselectedItemColor: Colors.grey[500],
    );
  }
}

4.4 第四步:搭建首页整体布局(核心重点)

首页是APP的“门面”,我们设计的风格是「简约、专业、易用」,贴合跨境溯源合规的产品调性,同时适配鸿蒙多设备显示。

lib/pages/home_page.dart中创建首页,整体布局分为4个部分:

  1. 顶部导航栏(复用上面创建的CustomAppBar);
  2. 核心区域:防伪码溯源查询入口(输入框+查询按钮);
  3. 功能入口区:快速进入合规检测、商家入驻、创业指南;
  4. 底部菜单栏(复用上面创建的CustomBottomNavBar)。
    在这里插入图片描述
核心设计思路(贴合用户场景):
  • 把「溯源查询」作为首页核心,放在最显眼的位置,因为这是消费者最常用的功能;
  • 功能入口区简洁明了,区分普通用户、商家、创业者的核心需求;
  • 鸿蒙多端适配:手机端垂直布局,平板/开发板横向布局,充分利用大屏空间;
  • 文字、组件尺寸自适应,避免大屏显示空洞、小屏显示拥挤。

关键代码(简化版,重点讲解布局逻辑):

import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:zhiandun_app/widgets/app_bar.dart';
import 'package:zhiandun_app/widgets/bottom_nav_bar.dart';
import 'package:zhiandun_app/widgets/custom_button.dart';
import 'package:zhiandun_app/widgets/custom_input.dart';

// 首页(鸿蒙多端适配)
class HomePage extends StatefulWidget {
  const HomePage({super.key});

  
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  int _currentIndex = 0; // 底部菜单当前选中索引
  final TextEditingController _codeController = TextEditingController(); // 防伪码输入控制器

  // 切换底部菜单
  void _onTabTap(int index) {
    setState(() {
      _currentIndex = index;
      // 后续添加页面切换逻辑,今天先完成UI
    });
  }

  // 溯源查询按钮点击事件(今天先做UI,后续添加业务逻辑)
  void _onQueryTap() {
    String code = _codeController.text.trim();
    if (code.isEmpty) {
      // 提示用户输入防伪码(后续添加弹窗提示)
      return;
    }
    // 后续添加溯源查询逻辑
  }

  
  Widget build(BuildContext context) {
    final isDayuOrTablet = MediaQuery.of(context).size.width >= 600;
    
    return Scaffold(
      // 顶部导航栏
      appBar: const CustomAppBar(title: '智安盾·跨境溯源合规平台'),
      // 主体内容
      body: Padding(
        padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 20.h),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            // 1. 溯源查询核心入口(最显眼位置)
            Text(
              '防伪码溯源查询',
              style: TextStyle(
                fontSize: isDayuOrTablet ? 22.sp : 18.sp,
                fontWeight: FontWeight.bold,
              ),
            ),
            SizedBox(height: 20.h),
            // 输入框+查询按钮(鸿蒙适配:大屏横向排列,小屏垂直排列)
            isDayuOrTablet
                ? Row(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      CustomInput(
                        controller: _codeController,
                        hintText: '请输入商品防伪码',
                      ),
                      SizedBox(width: 16.w),
                      CustomButton(
                        text: '立即查询',
                        onTap: _onQueryTap,
                      ),
                    ],
                  )
                : Column(
                    children: [
                      CustomInput(
                        controller: _codeController,
                        hintText: '请输入商品防伪码',
                      ),
                      SizedBox(height: 16.h),
                      CustomButton(
                        text: '立即查询',
                        onTap: _onQueryTap,
                      ),
                    ],
                  ),
            SizedBox(height: 40.h),
            // 2. 功能入口区(适配多设备)
            Text(
              '核心功能',
              style: TextStyle(
                fontSize: isDayuOrTablet ? 20.sp : 16.sp,
                fontWeight: FontWeight.bold,
              ),
            ),
            SizedBox(height: 20.h),
            // 功能卡片(鸿蒙适配:大屏3列,小屏2列)
            Expanded(
              child: GridView.count(
                crossAxisCount: isDayuOrTablet ? 3 : 2,
                crossAxisSpacing: 16.w,
                mainAxisSpacing: 16.h,
                childAspectRatio: isDayuOrTablet ? 1.2 : 1.1,
                children: [
                  // 合规检测卡片
                  _buildFunctionCard(
                    icon: Icons.shield,
                    title: '合规检测',
                    desc: '商家合规自查',
                    onTap: () {},
                  ),
                  // 商家入驻卡片
                  _buildFunctionCard(
                    icon: Icons.store,
                    title: '商家入驻',
                    desc: '快速合规上线',
                    onTap: () {},
                  ),
                  // 创业指南卡片
                  _buildFunctionCard(
                    icon: Icons.lightbulb,
                    title: '创业指南',
                    desc: '低成本起步',
                    onTap: () {},
                  ),
                  // 更多功能卡片(预留)
                  _buildFunctionCard(
                    icon: Icons.more_horiz,
                    title: '更多功能',
                    desc: '持续更新中',
                    onTap: () {},
                  ),
                ],
              ),
            ),
          ],
        ),
      ),
      // 底部菜单栏
      bottomNavigationBar: CustomBottomNavBar(
        currentIndex: _currentIndex,
        onTap: _onTabTap,
      ),
    );
  }

  // 功能卡片组件(复用)
  Widget _buildFunctionCard({
    required IconData icon,
    required String title,
    required String desc,
    required VoidCallback onTap,
  }) {
    final isDayuOrTablet = MediaQuery.of(context).size.width >= 600;
    
    return GestureDetector(
      onTap: onTap,
      child: Container(
        padding: EdgeInsets.all(16.w),
        decoration: BoxDecoration(
          color: Colors.white,
          borderRadius: BorderRadius.circular(8.r),
          boxShadow: [BoxShadow(color: Colors.grey[100], blurRadius: 4)],
        ),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Icon(
              icon,
              size: isDayuOrTablet ? 32.sp : 28.sp,
              color: Color(0xFF36CFC9),
            ),
            SizedBox(height: 12.h),
            Text(
              title,
              style: TextStyle(
                fontSize: isDayuOrTablet ? 16.sp : 14.sp,
                fontWeight: FontWeight.w500,
              ),
            ),
            SizedBox(height: 4.h),
            Text(
              desc,
              style: TextStyle(
                fontSize: isDayuOrTablet ? 12.sp : 11.sp,
                color: Colors.grey[500],
              ),
            ),
          ],
        ),
      ),
    );
  }
}

4.5 第五步:鸿蒙多端适配细节(重点!避坑关键)

今天的核心重点之一就是鸿蒙多端适配,我们已经在每个组件中做了适配,这里集中总结几个关键适配点,帮大家避开鸿蒙开发的常见坑:

  1. 触控区域适配:所有可点击组件(按钮、输入框、卡片、底部菜单),最小触控区域≥48dp,适配鸿蒙开发板、老人机的低精度触控;
  2. 尺寸自适应:通过MediaQuery判断设备尺寸,区分手机/平板/开发板,动态调整组件大小、文字大小,避免大屏空洞、小屏拥挤;
  3. 布局适配:大屏(平板/开发板)采用横向布局(输入框+按钮横向排列、功能卡片3列),小屏(手机)采用垂直布局,充分利用屏幕空间;
  4. 状态栏适配:统一导航栏状态栏样式,避免鸿蒙设备上状态栏文字与导航栏重叠,确保显示清晰;
  5. 性能优化:关闭多余动画、减少组件嵌套,保证鸿蒙开发板运行流畅,不卡顿。
    在这里插入图片描述

4.6 第六步:项目运行与测试

所有UI组件开发完成后,我们运行项目,在鸿蒙设备上测试,确保以下几点:

  1. 首页布局在手机、平板、开发板上显示正常,无错乱、无重叠;
  2. 所有按钮、输入框、卡片均可正常点击,触控灵敏,无误触;
  3. 文字大小、组件尺寸适配对应设备,可读性强;
  4. 页面滑动流畅,无卡顿、无闪退。

如果出现“组件显示错乱”,大概率是尺寸适配没有做好,检查MediaQuery判断逻辑、ScreenUtil的尺寸设置;如果出现“触控不灵敏”,检查组件的高度、宽度是否达到48dp的最小触控尺寸。

五、Day2 开发总结(口语化复盘,理清思路)

今天Day2,我们重点完成了「UI落地+鸿蒙多端适配」,整个过程没有复杂的业务逻辑,都是围绕“界面好看、操作顺手、多设备适配”展开,相信大家都能轻松跟上。

总结一下今天的核心收获:

  1. 学会了创建全局复用组件(按钮、输入框、导航栏、底部菜单),减少重复代码,统一UI风格;
  2. 完成了首页整体布局,把溯源查询核心入口放在最显眼的位置,贴合用户使用场景;
  3. 重点掌握了鸿蒙多端适配的核心技巧,解决了触控、尺寸、布局适配的常见问题;
  4. 成功运行项目,确保所有UI组件在鸿蒙设备上显示正常、操作流畅,为后续业务逻辑开发打好了基础。

这里提醒一句:UI开发没有绝对的标准,大家可以根据自己的喜好,调整颜色、布局、文字大小,但一定要记住「鸿蒙适配优先」,确保多设备显示正常,尤其是开发板的适配,这是我们Flutter+鸿蒙实战的核心重点。

六、下期内容预告

Day3我们将会进入「业务逻辑开发阶段」,内容干货满满,重点做2件事:

  1. 完成溯源查询核心逻辑开发,实现“输入防伪码→查询溯源信息”的完整流程;
  2. 开发鸿蒙网络请求适配,解决鸿蒙设备网络权限、接口请求的常见问题;
  3. 新增弹窗提示(输入为空、查询失败、查询成功),提升用户体验;
  4. 完善首页功能入口的跳转逻辑,实现页面之间的切换。
Logo

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

更多推荐