上一篇我们完成了 Flutter For OpenHarmony 鸿蒙 PC 开发的环境搭建,本篇将聚焦「第一个实战应用」—— 从窗口创建、PC 专属配置到大屏响应式布局,全程拆解开发流程,提供可直接下载复用的工程模板,帮助快速上手鸿蒙 PC 应用开发。

一、应用核心目标与技术要点

本次开发的鸿蒙 PC 应用为「基础演示工具」,核心实现以下功能,覆盖 PC 端开发核心场景:

  1. 鸿蒙 PC 专属窗口创建与配置(固定初始尺寸、支持缩放、窗口标题定制);
  2. 大屏响应式布局(适配 1080P/2K/4K 分辨率,区分横竖屏显示逻辑);
  3. PC 键鼠交互基础支持(鼠标悬停效果、滚轮滚动适配);
  4. 工程模板标准化(便于后续功能扩展与复用)。

核心技术栈:Flutter 3.13.0+ + 鸿蒙 PC SDK(API 11),无额外第三方依赖,确保环境兼容性。

二、工程初始化与目录结构(模板基础)

我们基于上一篇的环境,通过命令行创建标准化工程,同时梳理 PC 端专属目录结构,为窗口配置和布局开发铺垫。

2.1 工程创建

# 进入工作目录(无中文、无空格)
cd D:\FlutterOHOSProjects
# 创建鸿蒙 PC 专属 Flutter 工程(指定设备类型为 PC)
flutter create --template=ohos --device-type=pc flutter_ohos_pc_first_app
# 进入工程目录
cd flutter_ohos_pc_first_app
# 用 DevEco Studio 打开工程(自动关联鸿蒙 SDK)
devecostudio .

2.2 鸿蒙 PC 工程专属目录结构

flutter_ohos_pc_first_app/
├─ entry/  # 鸿蒙应用入口模块(PC 端核心配置目录)
│  └─ src/main/
│     ├─ ets/  # 鸿蒙原生代码目录(窗口配置关联)
│     ├─ resources/  # 资源目录(图标、字符串等)
│     └─ config.json  # 核心配置文件(窗口参数、权限等,PC 专属)
├─ lib/  # Flutter 业务代码目录
│  └─ main.dart  # 入口文件(布局实现、交互逻辑)
├─ pubspec.yaml  # Flutter 依赖配置文件
└─ ohos.yaml  # 鸿蒙工程配置文件(关联 Flutter 与鸿蒙原生)

⚠️ 关键提醒:PC 端开发需重点关注 entry/src/main/config.json(窗口配置)和 lib/main.dart(布局实现),二者联动实现应用可视化效果,区别于移动端的目录适配逻辑。

三、鸿蒙 PC 窗口创建与专属配置

鸿蒙 PC 应用的窗口特性(尺寸、缩放、标题栏)需通过 config.json 配置,再结合 Flutter 层初始化逻辑,实现窗口的完整创建。

3.1 config.json 窗口核心配置(PC 专属)

路径:entry/src/main/config.json,修改 abilities 节点下的窗口参数,配置后需同步保存工程,具体代码如下:

{
  "app": {
    "bundleName": "com.example.flutterohospcfirstapp",
    "vendor": "example",
    "version": {
      "code": 1000000,
      "name": "1.0.0"
    }
  },
  "module": {
    "name": "entry",
    "type": "entry",
    "srcPath": "./src/main/ets",
    "deviceType": ["pc"],  // 仅保留 PC 设备类型,排除其他端
    "minAPIVersion": 11,
    "abilities": [
      {
        "name": ".MainAbility",
        "type": "page",
        "launchType": "standard",
        "orientation": "unspecified",  # 支持横竖屏自适应(PC 大屏必备)
        "windowMode": "windowed",  # 窗口模式(fullscreen 为全屏模式)
        "defaultWidth": 1280,  # 初始宽度(适配 2K 屏基础尺寸)
        "defaultHeight": 720,  # 初始高度(16:9 黄金比例,适配多数 PC)
        "resizable": true,  # 允许窗口缩放(PC 端核心交互需求)
        "titleBar": true,  # 显示系统标题栏(可自定义标题)
        "title": "Flutter 鸿蒙 PC 演示应用",  # 窗口标题(PC 专属)
        "icon": "$media:icon",  # 窗口图标(从 resources 目录读取)
        "label": "$string:app_name"
      }
    ],
    "reqPermissions": []  # 本次无额外权限需求,留空即可
  }
}

配置说明:

  • windowMode:可选 windowed(窗口)、fullscreen(全屏),PC 端开发优先选 windowed,支持用户手动切换全屏;
  • resizable:必须设为 true,否则窗口无法缩放,不符合 PC 端使用习惯;
  • defaultWidth/defaultHeight:建议以 1280x720 为基础,适配主流 PC 分辨率,后续布局通过响应式适配更高分辨率。

3.2 Flutter 层窗口初始化关联

路径:lib/main.dart,初始化 Flutter 应用时,需开启 PC 端键鼠交互支持,确保窗口加载后能响应鼠标悬停、滚轮等事件,基础初始化代码如下:

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

void main() {
  runApp(const MyApp());
  // 可选:设置窗口最小尺寸(PC 端专属限制,避免窗口过小导致布局错乱)
  SystemChrome.setPreferredOrientations([
    DeviceOrientation.landscapeLeft,
    DeviceOrientation.landscapeRight,
    DeviceOrientation.portraitUp,
  ]);
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter 鸿蒙 PC 应用',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        // PC 端字体适配:默认字体略大于移动端,提升大屏可读性
        textTheme: const TextTheme(
          bodyLarge: TextStyle(fontSize: 16),
          bodyMedium: TextStyle(fontSize: 14),
        ),
      ),
      home: const HomePage(),
      // 开启 PC 端鼠标交互支持(悬停、滚轮)
      scrollBehavior: const MaterialScrollBehavior().copyWith(
        dragDevices: {
          PointerDeviceKind.mouse,
          PointerDeviceKind.touch,
        },
      ),
      debugShowCheckedModeBanner: false,  // 隐藏调试横幅
    );
  }
}

四、鸿蒙 PC 大屏响应式布局实现

鸿蒙 PC 端屏幕尺寸差异大(13 寸笔记本到 27 寸显示器),需采用响应式布局,确保在不同分辨率下布局合理、交互流畅。本次实现「左右分栏 + 自适应折叠」布局,核心用 LayoutBuilderMediaQuery 组件。

4.1 完整布局代码(可直接运行)

lib/main.dart 中补充 HomePage 组件,实现大屏分栏、小屏折叠的响应式逻辑,同时添加鼠标悬停效果:

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

  @override
  Widget build(BuildContext context) {
    // 获取当前窗口尺寸,用于响应式判断
    final screenSize = MediaQuery.of(context).size;
    // 定义分栏阈值:宽度 > 800 时分栏,否则垂直折叠
    final isWideScreen = screenSize.width > 800;

    return Scaffold(
      // PC 端标题栏:结合鸿蒙原生窗口标题,添加自定义操作按钮
      appBar: AppBar(
        title: const Text('鸿蒙 PC 演示应用'),
        toolbarHeight: 48,  // PC 端标题栏高度适配(高于移动端的 56)
        actions: [
          IconButton(
            icon: const Icon(Icons.settings),
            onPressed: () {
              // 后续可扩展设置功能
              ScaffoldMessenger.of(context).showSnackBar(
                const SnackBar(content: Text('设置功能待扩展')),
              );
            },
            tooltip: '设置',  // PC 端鼠标悬停提示
            hoverColor: Colors.blue[100],  // 鼠标悬停背景色
          ),
        ],
      ),
      body: LayoutBuilder(
        builder: (context, constraints) {
          return isWideScreen
              ? _buildWideScreenLayout(constraints)
              : _buildNarrowScreenLayout(constraints);
        },
      ),
    );
  }

  // 宽屏布局(左右分栏)
  Widget _buildWideScreenLayout(BoxConstraints constraints) {
    return Row(
      children: [
        // 左侧导航栏(占比 25%,固定宽度不拉伸)
        Container(
          width: constraints.maxWidth * 0.25,
          color: Colors.grey[100],
          padding: const EdgeInsets.symmetric(vertical: 20),
          child: ListView(
            children: [
              _buildNavItem('首页', Icons.home),
              _buildNavItem('数据展示', Icons.data_usage),
              _buildNavItem('关于', Icons.info),
            ],
          ),
        ),
        // 右侧内容区(占比 75%,填充剩余空间)
        Expanded(
          child: Container(
            padding: const EdgeInsets.all(30),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                const Text(
                  '鸿蒙 PC 大屏布局演示',
                  style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
                ),
                const SizedBox(height: 20),
                // 数据卡片(PC 端大屏适配,多卡片横向排列)
                Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  children: [
                    _buildDataCard('在线人数', '128', Colors.blue),
                    _buildDataCard('运行时长', '24h', Colors.green),
                    _buildDataCard('版本号', '1.0.0', Colors.orange),
                  ],
                ),
                const SizedBox(height: 30),
                const Text(
                  '布局说明:当前为宽屏模式(宽度 > 800px),采用左右分栏布局,适配 2K/4K 显示器。拖动窗口边缘缩小宽度,将自动切换为垂直布局。',
                  style: TextStyle(color: Colors.grey[600], fontSize: 14),
                ),
              ],
            ),
          ),
        ),
      ],
    );
  }

  // 窄屏布局(垂直折叠)
  Widget _buildNarrowScreenLayout(BoxConstraints constraints) {
    return Column(
      children: [
        // 顶部导航栏(替代左侧分栏)
        Container(
          height: 56,
          color: Colors.grey[100],
          child: Row(
            mainAxisAlignment: MainAxisAlignment.spaceAround,
            children: [
              _buildNavItemNarrow('首页', Icons.home),
              _buildNavItemNarrow('数据展示', Icons.data_usage),
              _buildNavItemNarrow('关于', Icons.info),
            ],
          ),
        ),
        // 下方内容区
        Expanded(
          child: Container(
            padding: const EdgeInsets.all(20),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                const Text(
                  '鸿蒙 PC 窄屏布局演示',
                  style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
                ),
                const SizedBox(height: 20),
                // 数据卡片(垂直排列)
                Column(
                  children: [
                    _buildDataCard('在线人数', '128', Colors.blue),
                    const SizedBox(height: 15),
                    _buildDataCard('运行时长', '24h', Colors.green),
                    const SizedBox(height: 15),
                    _buildDataCard('版本号', '1.0.0', Colors.orange),
                  ],
                ),
              ],
            ),
          ),
        ),
      ],
    );
  }

  // 宽屏导航项(带鼠标悬停效果)
  Widget _buildNavItem(String title, IconData icon) {
    return ListTile(
      leading: Icon(icon, color: Colors.blue),
      title: Text(title),
      onTap: () {},
      hoverTileColor: Colors.blue[50],  // 鼠标悬停背景色
      selectedTileColor: Colors.blue[100],
      selected: title == '首页',  // 默认选中首页
    );
  }

  // 窄屏导航项
  Widget _buildNavItemNarrow(String title, IconData icon) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        Icon(icon, color: Colors.blue),
        const SizedBox(height: 4),
        Text(title, style: const TextStyle(fontSize: 12)),
      ],
    );
  }

  // 数据卡片组件(复用)
  Widget _buildDataCard(String title, String value, Color color) {
    return Container(
      width: 180,
      padding: const EdgeInsets.all(20),
      decoration: BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.circular(8),
        boxShadow: [
          BoxShadow(
            color: Colors.grey[200],
            blurRadius: 4,
            offset: const Offset(0, 2),
          ),
        ],
        borderLeft: Border(left: BorderSide(color: color, width: 4)),
      ),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Text(title, style: TextStyle(color: Colors.grey[600], fontSize: 14)),
          const SizedBox(height: 8),
          Text(
            value,
            style: TextStyle(color: color, fontSize: 22, fontWeight: FontWeight.bold),
          ),
        ],
      ),
    );
  }
}

4.2 布局核心适配要点(PC 端专属)

  1. 分栏阈值设定:以 800px 为分界,宽屏时分栏、窄屏时折叠,适配笔记本小屏与台式机大屏;
  2. 组件尺寸适配:PC 端标题栏高度、字体大小、卡片尺寸均大于移动端,提升大屏操作与阅读体验;
  3. 键鼠交互优化:添加 hoverColortooltip 等鼠标悬停特性,符合 PC 端操作习惯,区别于移动端的触摸交互;
  4. 布局复用:提取 _buildDataCard_buildNavItem 等复用组件,降低后续扩展成本。

五、应用运行与效果验证

5.1 运行步骤(同前序流程,简化版)

  1. 启动鸿蒙 PC 模拟器(或连接真机):在 DevEco Studio 工具栏打开「Device Manager」,启动已创建的 PC 模拟器(推荐 1280x720 分辨率);
  2. 运行应用:点击工具栏「Run 'entry'」(绿色三角按钮),IDE 自动编译工程并安装到模拟器;
  3. 效果验证:应用启动后,观察窗口特性与布局适配效果。

5.2 核心验证点

验证项 预期效果
窗口特性 初始尺寸 1280x720,可拖动边缘缩放,标题栏显示「Flutter 鸿蒙 PC 演示应用」
布局适配 窗口宽度 > 800px 时左右分栏,< 800px 时垂直折叠,布局自动重绘
键鼠交互 鼠标悬停导航项时显示背景色,点击设置图标弹出提示,滚轮可滚动内容区

六、可运行工程模板获取与使用

6.1 模板获取

  1. 访问鸿蒙开发者社区,搜索「Flutter 鸿蒙 PC 第一个应用模板」;
  2. 下载模板压缩包,解压至无中文路径(如:D:\FlutterTemplates);
  3. 用 DevEco Studio 打开解压后的工程,自动加载依赖(首次打开需等待 npm 安装依赖)。

6.2 模板使用注意事项

  1. 依赖校验:打开工程后,执行 flutter ohos doctor 校验依赖,确保无报错;
  2. 包名修改:根据自身需求修改 config.json 中的 bundleName(需唯一,遵循反向域名规则);
  3. 图标替换:替换 entry/src/main/resources/media 目录下的图标文件,适配 PC 端窗口图标显示。

七、常见问题排查

问题现象 原因分析 解决方案
窗口无法缩放 config.jsonresizable 设为 false,或未配置该参数 修改 resizable 为 true,保存后重新编译运行
鼠标悬停无效果 Flutter 层未配置 scrollBehavior 支持鼠标设备 参照 3.2 节代码,添加鼠标设备支持配置
布局错乱(组件重叠) 未使用 LayoutBuilderMediaQuery,固定了组件绝对尺寸 替换为响应式布局逻辑,用相对尺寸(占比、自适应)替代绝对尺寸
应用启动后无窗口标题 未在 config.json 中配置 title 参数 补充 title 字段,设置自定义窗口标题

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

欢迎加入开源鸿蒙 PC 社区:https://harmonypc.csdn.net/

Logo

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

更多推荐