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

前言:跨生态开发的新机遇

在移动开发领域,我们总是面临着选择与适配。今天,你的Flutter应用在Android和iOS上运行良好,明天可能就需要考虑一个新的平台:HarmonyOS(鸿蒙)。这不是一道选答题,而是很多团队正在面对的现实。

Flutter的优势显而易见——编写一套代码,就能在两个主要平台上运行,开发体验流畅。而鸿蒙代表的是下一个时代的互联生态,它不仅仅是手机系统,更着眼于未来全场景的体验。将现有的Flutter应用适配到鸿蒙,听起来像是一个“跨界”任务,但它本质上是一次有价值的技术拓展:让产品触达更多用户,也让技术栈覆盖更广。

不过,这条路走起来并不像听起来那么简单。Flutter和鸿蒙,从底层的架构到上层的工具链,都有着各自的设计逻辑。开发过程中会遇到一些具体的问题:代码如何组织?原有的功能在鸿蒙上如何实现?那些平台特有的能力该怎么调用?更实际的是,从编译打包到上架部署,整个流程都需要重新摸索。
本文旨在将这些我们趟过的路、踩过的坑,清晰地摊开给你看。我们不会只停留在“怎么做”,还会聊到“为什么得这么做”,以及“如果出了问题该往哪想”。这更像是一份实战笔记,源自真实的项目经验,聚焦于那些真正卡住过我们的环节。

无论你是在为一个成熟产品寻找新的落地平台,还是从一开始就希望构建能面向多端的应用,这里的思路和解决方案都能提供直接的参考。理解了两套体系之间的异同,掌握了关键的衔接技术,不仅能完成这次迁移,更能积累起应对未来技术变化的能力。

混合工程结构深度解析

项目目录架构

当Flutter项目集成鸿蒙支持后,典型的项目结构会发生显著变化。以下是经过ohos_flutter插件初始化后的项目结构:

my_flutter_harmony_app/
├── lib/                          # Flutter业务代码(基本不变)
│   ├── main.dart                 # 应用入口
│   ├── home_page.dart           # 首页
│   └── utils/
│       └── platform_utils.dart  # 平台工具类
├── pubspec.yaml                  # Flutter依赖配置
├── ohos/                         # 鸿蒙原生层(核心适配区)
│   ├── entry/                    # 主模块
│   │   └── src/main/
│   │       ├── ets/              # ArkTS代码
│   │       │   ├── MainAbility/
│   │       │   │   ├── MainAbility.ts       # 主Ability
│   │       │   │   └── MainAbilityContext.ts
│   │       │   └── pages/
│   │       │       ├── Index.ets           # 主页面
│   │       │       └── Splash.ets          # 启动页
│   │       ├── resources/        # 鸿蒙资源文件
│   │       │   ├── base/
│   │       │   │   ├── element/  # 字符串等
│   │       │   │   ├── media/    # 图片资源
│   │       │   │   └── profile/  # 配置文件
│   │       │   └── en_US/        # 英文资源
│   │       └── config.json       # 应用核心配置
│   ├── ohos_test/               # 测试模块
│   ├── build-profile.json5      # 构建配置
│   └── oh-package.json5         # 鸿蒙依赖管理
└── README.md

目录

展示效果图片

flutter 实时预览 效果展示
在这里插入图片描述

运行到鸿蒙虚拟设备中效果展示
在这里插入图片描述

功能代码实现

搜索关键词高亮组件

实现细节

搜索关键词高亮组件是一个使用RichText和字符串匹配实现的Flutter组件,用于实时高亮显示文本中的搜索关键词。该组件通过以下技术实现:

  1. 实时搜索:用户输入关键词时,实时高亮显示匹配的文本
  2. 大小写不敏感:搜索匹配时忽略大小写,提高用户体验
  3. 预设关键词:提供常用关键词按钮,方便用户快速搜索
  4. 美观的UI设计:采用现代化的搜索框设计和高亮效果

核心代码实现

组件结构
import 'package:flutter/material.dart';

class SearchHighlight extends StatefulWidget {
  final double width;
  final double height;
  final Color backgroundColor;
  final Color primaryColor;
  final Color highlightColor;

  const SearchHighlight({
    Key? key,
    this.width = double.infinity,
    this.height = 400,
    this.backgroundColor = Colors.white,
    this.primaryColor = Colors.blue,
    this.highlightColor = Colors.yellow,
  }) : super(key: key);

  
  State<SearchHighlight> createState() => _SearchHighlightState();
}

class _SearchHighlightState extends State<SearchHighlight> {
  TextEditingController _searchController = TextEditingController();
  String _searchText = '';
  String _content = 'Flutter是谷歌推出的开源移动应用开发框架,使用Dart语言开发,支持跨平台开发。Flutter的优势在于热重载、丰富的UI组件和高性能。OpenHarmony是华为推出的开源操作系统,支持多种设备类型。Flutter for OpenHarmony允许开发者使用Flutter开发OpenHarmony应用。';

  
  void dispose() {
    _searchController.dispose();
    super.dispose();
  }

  
  Widget build(BuildContext context) {
    return Container(
      padding: EdgeInsets.all(16.0),
      color: widget.backgroundColor,
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
          // 标题
          Text(
            '搜索关键词高亮',
            style: TextStyle(
              fontSize: 18,
              fontWeight: FontWeight.bold,
              color: widget.primaryColor,
            ),
          ),
          SizedBox(height: 20),

          // 搜索输入框
          Container(
            width: double.infinity,
            height: 50,
            decoration: BoxDecoration(
              borderRadius: BorderRadius.circular(25),
              color: Colors.grey[200],
            ),
            child: Row(
              children: [
                SizedBox(width: 16),
                Icon(
                  Icons.search,
                  color: Colors.grey[600],
                ),
                SizedBox(width: 12),
                Expanded(
                  child: TextField(
                    controller: _searchController,
                    onChanged: (value) {
                      setState(() {
                        _searchText = value;
                      });
                    },
                    decoration: InputDecoration(
                      border: InputBorder.none,
                      hintText: '输入关键词搜索',
                      hintStyle: TextStyle(
                        color: Colors.grey[500],
                      ),
                    ),
                  ),
                ),
                SizedBox(width: 16),
              ],
            ),
          ),
          SizedBox(height: 20),

          // 内容展示区域
          Container(
            width: double.infinity,
            padding: EdgeInsets.all(16.0),
            decoration: BoxDecoration(
              borderRadius: BorderRadius.circular(12),
              border: Border.all(
                width: 1,
                color: Colors.grey[300] ?? Colors.grey,
              ),
            ),
            child: _buildHighlightedText(),
          ),
          SizedBox(height: 20),

          // 预设关键词
          Text('预设关键词'),
          SizedBox(height: 12),
          Wrap(
            spacing: 12,
            runSpacing: 8,
            alignment: WrapAlignment.center,
            children: [
              'Flutter',
              'OpenHarmony',
              'Dart',
              '跨平台',
              '开源',
            ].map((keyword) {
              return GestureDetector(
                onTap: () {
                  setState(() {
                    _searchText = keyword;
                    _searchController.text = keyword;
                  });
                },
                child: Container(
                  padding: EdgeInsets.symmetric(
                    horizontal: 16,
                    vertical: 8,
                  ),
                  decoration: BoxDecoration(
                    borderRadius: BorderRadius.circular(16),
                    color: _searchText == keyword
                        ? widget.primaryColor
                        : Colors.grey[200],
                  ),
                  child: Text(
                    keyword,
                    style: TextStyle(
                      color: _searchText == keyword
                          ? Colors.white
                          : Colors.black87,
                    ),
                  ),
                ),
              );
            }).toList(),
          ),
          SizedBox(height: 20),

          // 操作提示
          Text(
            '提示:输入关键词或点击预设关键词查看高亮效果',
            style: TextStyle(
              fontSize: 14,
              color: Colors.grey[600],
            ),
          ),
        ],
      ),
    );
  }

  Widget _buildHighlightedText() {
    if (_searchText.isEmpty) {
      return Text(
        _content,
        style: TextStyle(
          fontSize: 16,
          color: Colors.black87,
          height: 1.5,
        ),
      );
    }

    List<TextSpan> spans = [];
    int start = 0;
    int index = _content.toLowerCase().indexOf(_searchText.toLowerCase(), start);

    while (index != -1) {
      // 添加搜索词之前的文本
      spans.add(TextSpan(
        text: _content.substring(start, index),
        style: TextStyle(
          fontSize: 16,
          color: Colors.black87,
          height: 1.5,
        ),
      ));

      // 添加高亮的搜索词
      spans.add(TextSpan(
        text: _content.substring(index, index + _searchText.length),
        style: TextStyle(
          fontSize: 16,
          color: Colors.black87,
          backgroundColor: widget.highlightColor,
          fontWeight: FontWeight.bold,
          height: 1.5,
        ),
      ));

      // 更新起始位置
      start = index + _searchText.length;
      index = _content.toLowerCase().indexOf(_searchText.toLowerCase(), start);
    }

    // 添加剩余的文本
    spans.add(TextSpan(
      text: _content.substring(start),
      style: TextStyle(
        fontSize: 16,
        color: Colors.black87,
        height: 1.5,
      ),
    ));

    return RichText(
      text: TextSpan(children: spans),
    );
  }
}

使用方法

基本使用
import 'components/search_highlight.dart';

// 在需要的地方使用
SearchHighlight()
自定义配置
// 自定义宽度、高度和颜色
SearchHighlight(
  width: 300,
  height: 400,
  backgroundColor: Colors.grey[100]!,
  primaryColor: Colors.green,
  highlightColor: Colors.yellowAccent,
)

在主应用中的集成

以下是在主应用中集成搜索关键词高亮组件的代码:

import 'package:flutter/material.dart';
import 'components/search_highlight.dart';

void main() {
  runApp(const MyApp());
}

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

  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter for openHarmony',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      debugShowCheckedModeBanner: false,
      home: const MyHomePage(title: 'Flutter for openHarmony'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
        centerTitle: true,
      ),
      body: SingleChildScrollView(
        padding: EdgeInsets.all(16.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: <Widget>[
            // 搜索关键词高亮
            Card(
              elevation: 4,
              margin: EdgeInsets.only(bottom: 20),
              child: SearchHighlight(),
            ),
          ],
        ),
      ),
    );
  }
}

开发中需要注意的点

  1. 字符串匹配大小写处理:在实现搜索功能时,使用toLowerCase()方法确保大小写不敏感的匹配,提高用户体验。

  2. 空值处理:在使用Colors.grey[300]等可能返回null的颜色值时,使用??运算符提供默认值,避免类型错误。

  3. 状态管理:使用setState方法更新状态时,确保只更新必要的部分,避免不必要的重建。

  4. 文本控制器管理:使用TextEditingController时,记得在dispose方法中调用dispose(),避免内存泄漏。

  5. 响应式布局:使用Wrap组件实现预设关键词的自适应布局,确保界面在不同屏幕尺寸上都能正常显示。

  6. 用户体验:添加适当的间距和动画效果,提升界面美观度和用户体验。

本次开发中容易遇到的问题

  1. Flutter SDK权限问题:在运行Flutter命令时可能会遇到权限不足的问题,导致无法正常构建和运行项目。解决方法是确保Flutter SDK目录有正确的读写权限。

  2. 组件导入路径错误:在导入自定义组件时,可能会因为路径错误导致编译失败。解决方法是使用相对路径或绝对路径正确导入组件。

  3. 状态管理问题:在使用setState更新状态时,可能会因为状态更新逻辑不正确导致界面不刷新。解决方法是确保所有需要更新的状态都通过setState方法进行更新。

  4. 颜色处理问题:在处理颜色时,可能会因为颜色值为null导致运行时错误。解决方法是使用??运算符为可能为null的颜色值提供默认值。

  5. 布局适配问题:在不同屏幕尺寸上,组件可能会出现布局错乱的问题。解决方法是使用WrapFlex等自适应布局组件,确保界面在不同屏幕尺寸上都能正常显示。

  6. 组件不存在错误:在引用不存在的组件时,会导致编译失败。解决方法是确保只引用项目中实际存在的组件,移除对不存在组件的引用。

  7. 字符串匹配问题:在实现搜索关键词高亮时,可能会因为字符串匹配逻辑不正确导致高亮效果不准确。解决方法是使用toLowerCase()方法确保大小写不敏感的匹配,并正确处理字符串的索引和截取。

总结本次开发中用到的技术点

  1. Flutter组件化开发:将搜索关键词高亮功能封装为独立的SearchHighlight组件,提高代码复用性和可维护性。

  2. 状态管理:使用setState方法管理组件状态,实现实时搜索和高亮效果。

  3. 交互设计:使用GestureDetector实现点击交互效果,通过颜色变化反馈用户操作。

  4. 布局组件:使用WrapSingleChildScrollViewCard等组件实现自适应布局。

  5. 参数化设计:通过构造函数参数化组件配置,允许用户自定义组件宽度、高度、背景色、主题色和高亮色。

  6. 响应式设计:使用自适应布局组件,确保界面在不同屏幕尺寸上都能正常显示。

  7. 图标使用:使用Icons类提供的图标,丰富界面设计。

  8. 字符串处理:使用字符串匹配和截取实现关键词高亮功能。

  9. 主题配置:在主应用中配置主题,确保整个应用的视觉风格一致。

  10. 错误处理:通过移除对不存在组件的引用,解决编译错误。

  11. RichText使用:使用RichTextTextSpan实现文本的部分高亮效果,这是实现关键词高亮的核心技术。

  12. TextField使用:使用TextField实现用户输入,并通过onChanged回调实时处理输入内容。

  13. TextEditingController:使用TextEditingController控制文本输入框的内容,实现预设关键词的快速填充。

  14. 空值安全:使用??运算符处理可能为null的值,确保代码的健壮性。

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

Logo

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

更多推荐