【Flutter For OpenHarmony 第三方库】Flutter 三方库鸿蒙化:鸿蒙 App 启动页与引导页
在 Flutter 开发 OpenHarmony 应用过程中,启动页 + 新手引导页是几乎所有 App 的标配基础功能。本文基于 Flutter 框架,搭配已完成鸿蒙适配的三方库,从零手把手实现 App 冷启动白屏优化、自定义全屏启动页、轮播引导页、首次安装进入引导页、非首次直接跳转主页完整逻辑。操作步骤清晰、代码可直接复用、适配鸿蒙平台无白屏无崩溃,适合作为 Flutter 鸿蒙应用开发入门实战
欢迎加入开源鸿蒙跨平台开发者社区:https://openharmonycrossplatform.csdn.net
摘要
在 Flutter 开发 OpenHarmony 应用过程中,启动页 + 新手引导页是几乎所有 App 的标配基础功能。本文基于 Flutter 框架,搭配已完成鸿蒙适配的三方库,从零手把手实现 App 冷启动白屏优化、自定义全屏启动页、轮播引导页、首次安装进入引导页、非首次直接跳转主页完整逻辑。操作步骤清晰、代码可直接复用、适配鸿蒙平台无白屏无崩溃,适合作为 Flutter 鸿蒙应用开发入门实战案例,全程使用鸿蒙化三方库,无任何未适配依赖,可直接在 OpenHarmony 设备编译运行。
一、项目实现功能
-
自定义 Flutter 全屏启动页,优化鸿蒙原生冷启动白屏问题
-
新手 3 页轮播引导页,支持左右滑动、页面指示器切换
-
基于鸿蒙化三方库实现本地持久化存储,标记 App 是否首次打开
-
首次安装打开:启动页(延时2秒)→ 引导页
-
非首次打开:启动页(延时2秒)→ 直接进入主页
-
全部依赖使用 OpenHarmony 已适配三方库,无编译报错、无运行崩溃
-
界面自适应鸿蒙设备屏幕,兼容手机、平板等鸿蒙终端
二、技术选型与鸿蒙化三方库
所有依赖均来自 OpenHarmony TPC Flutter 生态仓库,已完成鸿蒙化适配,可安全用于鸿蒙应用开发,无需额外适配操作,直接调用即可:
| 三方库 | 作用 | 鸿蒙适配状态 |
|---|---|---|
| flutter | 跨平台 UI 框架,实现页面渲染与交互 | ✅ 官方支持,兼容 OpenHarmony |
| provider | 全局状态管理,管理启动页、引导页跳转逻辑与本地存储状态 | ✅ 已鸿蒙化,稳定运行无异常 |
| shared_preferences | 本地轻量持久化存储,标记 App 是否首次打开,重启后状态不丢失 | ✅ 已鸿蒙化,适配鸿蒙存储机制 |
三、开发环境要求
确保环境配置符合以下要求,避免编译报错,全程可顺利跟着操作:
-
Flutter SDK:3.10 及以上稳定版(推荐使用 Flutter-OpenHarmony 定制版,支持鸿蒙编译)
-
开发工具:VS Code 或 Android Studio(安装 Flutter 插件)
-
鸿蒙运行环境:DevEco Studio(用于连接鸿蒙模拟器/真机运行)
-
项目路径:纯英文、无中文、无空格、无特殊字符(避免 hvigor、ohpm 编译报错)
四、创建项目与配置依赖
4.1 创建 Flutter 项目
打开终端,执行以下命令创建项目(复制粘贴即可,无需修改):
flutter create splash_guide_app
cd splash_guide_app
4.2 配置 pubspec.yaml 依赖
打开项目根目录下的 pubspec\.yaml 文件,在 dependencies 节点下添加鸿蒙化三方库依赖,完整配置如下:
dependencies:
flutter:
sdk: flutter
# 鸿蒙化三方库(已适配 OpenHarmony)
provider: ^6.1.2
shared_preferences: ^2.2.3
添加完成后,在终端执行以下命令安装依赖:
flutter pub get
等待依赖安装完成,无报错即配置成功。
五、全局状态管理封装(核心逻辑)
新建 lib/app\_provider\.dart 文件,用于管理 App 启动状态、首次打开标记,兼容鸿蒙环境,增加异常捕获避免白屏:
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
class AppProvider extends ChangeNotifier {
bool _isFirstOpen = true; // 是否首次打开 App
bool _splashEnd = false; // 启动页是否结束
// 对外提供获取状态的方法
bool get isFirstOpen => _isFirstOpen;
bool get splashEnd => _splashEnd;
// 初始化 App 状态(读取本地存储,判断是否首次打开)
Future<void> initAppFlag() async {
try {
SharedPreferences prefs = await SharedPreferences.getInstance();
// 读取本地存储的标记,默认是首次打开(true)
_isFirstOpen = prefs.getBool("isFirstOpen") ?? true;
} catch (e) {
// 鸿蒙环境存储初始化异常时,默认视为首次打开
_isFirstOpen = true;
debugPrint("鸿蒙存储初始化异常:$e");
}
// 模拟启动页延时 2 秒(可根据需求调整)
await Future.delayed(const Duration(seconds: 2));
_splashEnd = true; // 标记启动页结束
notifyListeners(); // 通知页面更新状态
}
// 进入主页后,标记为非首次打开(写入本地存储)
Future<void> setNotFirst() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
await prefs.setBool("isFirstOpen", false);
_isFirstOpen = false;
notifyListeners();
}
}
六、自定义启动页页面(优化鸿蒙白屏)
新建 lib/splash\_page\.dart 文件,实现全屏启动页,优化鸿蒙原生冷启动白屏问题,界面简洁美观,可直接复用:
import 'package:flutter/material.dart';
class SplashPage extends StatelessWidget {
const SplashPage({super.key});
Widget build(BuildContext context) {
// 全屏启动页,背景色可根据需求修改
return Scaffold(
backgroundColor: Colors.blueAccent,
body: SizedBox.expand(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: const [
// 启动页图标(可替换为自己的 App 图标)
Icon(Icons.android, size: 100, color: Colors.white),
SizedBox(height: 20),
// 启动页文字
Text(
"鸿蒙 Flutter 应用",
style: TextStyle(fontSize: 24, color: Colors.white, fontWeight: FontWeight.w500),
),
SizedBox(height: 30),
// 加载指示器
CircularProgressIndicator(color: Colors.white, strokeWidth: 3),
],
),
),
);
}
}
七、轮播引导页实现(新手引导)
新建 lib/guide\_page\.dart 文件,实现 3 页轮播引导页,支持左右滑动、页面指示器、下一页/开始使用按钮,逻辑完整:
import 'package:flutter/material.dart';
import 'app_provider.dart';
import 'package:provider/provider.dart';
class GuidePage extends StatefulWidget {
const GuidePage({super.key});
State<GuidePage> createState() => _GuidePageState();
}
class _GuidePageState extends State<GuidePage> {
final PageController _pageCtrl = PageController(); // 页面控制器,控制轮播
int _currentIndex = 0; // 当前引导页索引
// 引导页数据(可根据需求修改文字和图标)
final List<Map<String, dynamic>> _guideList = [
{"title": "高性能跨平台", "desc": "Flutter 一套代码,多端运行", "icon": Icons.speed},
{"title": "完美适配鸿蒙", "desc": "兼容所有 OpenHarmony 设备", "icon": Icons.device_hub},
{"title": "开启全新体验", "desc": "简单操作,高效便捷", "icon": Icons.emoji_emotions},
];
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
// 引导页轮播区域
Expanded(
child: PageView.builder(
controller: _pageCtrl,
itemCount: _guideList.length,
onPageChanged: (index) {
// 页面切换时,更新当前索引
setState(() => _currentIndex = index);
},
itemBuilder: (ctx, index) {
// 构建每一页引导页
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
_guideList[index]["icon"],
size: 120,
color: Colors.blue,
),
const SizedBox(height: 30),
Text(
_guideList[index]["title"],
style: const TextStyle(fontSize: 22, fontWeight: FontWeight.bold),
),
const SizedBox(height: 15),
Text(
_guideList[index]["desc"],
style: const TextStyle(fontSize: 16, color: Colors.grey),
),
],
),
);
},
),
),
// 底部指示器 + 按钮区域
Padding(
padding: const EdgeInsets.all(30),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
// 圆点指示器(根据引导页数量动态生成)
Row(
children: List.generate(_guideList.length, (index) {
return Container(
margin: const EdgeInsets.symmetric(horizontal: 4),
width: _currentIndex == index ? 12 : 8,
height: 8,
decoration: BoxDecoration(
color: _currentIndex == index ? Colors.blue : Colors.grey[300],
borderRadius: BorderRadius.circular(4),
),
);
}),
),
// 跳过/下一页/开始使用按钮
ElevatedButton(
onPressed: () async {
if (_currentIndex == _guideList.length - 1) {
// 最后一页,点击「开始使用」,标记非首次,跳转主页
await Provider.of<AppProvider>(context, listen: false)
.setNotFirst();
Navigator.pushReplacementNamed(context, "/home");
} else {
// 非最后一页,点击「下一页」,跳转到下一页引导页
_pageCtrl.nextPage(
duration: const Duration(milliseconds: 300),
curve: Curves.easeInOut,
);
}
},
style: ElevatedButton.styleFrom(
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
borderRadius: BorderRadius.circular(30),
),
child: Text(
_currentIndex == _guideList.length - 1 ? "开始使用" : "下一页",
style: const TextStyle(fontSize: 16),
),
),
],
),
)
],
),
);
}
}
八、主页简单示例(可直接扩展)
新建 lib/home\_page\.dart 文件,实现主页基础布局,无语法错误,可根据实际需求扩展功能:
import 'package:flutter/material.dart';
class HomePage extends StatelessWidget {
const HomePage({super.key});
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("App 首页"),
centerTitle: true,
backgroundColor: Colors.blueAccent,
),
body: const Center(
child: Text(
"欢迎使用 Flutter 鸿蒙应用",
style: TextStyle(fontSize: 20, color: Colors.black87),
),
),
);
}
}
九、主入口整合路由逻辑(核心跳转)
修改 lib/main\.dart 文件,整合路由分发、状态管理,实现启动页、引导页、主页的自动跳转逻辑,兼容鸿蒙环境,无白屏:
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'app_provider.dart';
import 'splash_page.dart';
import 'guide_page.dart';
import 'home_page.dart';
void main() {
// 确保 Flutter 初始化完成,避免鸿蒙环境下白屏
WidgetsFlutterBinding.ensureInitialized();
runApp(
// 提供全局状态管理
ChangeNotifierProvider(
create: (context) => AppProvider(),
child: const MyApp(),
),
);
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
Widget build(BuildContext context) {
return MaterialApp(
title: "鸿蒙启动页与引导页",
debugShowCheckedModeBanner: false, // 隐藏调试横幅
initialRoute: "/", // 初始路由
routes: {
"/": (ctx) => const RouteSwitchPage(), // 路由分发页
"/guide": (ctx) => const GuidePage(), // 引导页
"/home": (ctx) => const HomePage(), // 主页
},
);
}
}
// 路由逻辑分发页:根据启动状态和首次打开标记,跳转对应页面
class RouteSwitchPage extends StatefulWidget {
const RouteSwitchPage({super.key});
State<RouteSwitchPage> createState() => _RouteSwitchPageState();
}
class _RouteSwitchPageState extends State<RouteSwitchPage> {
void initState() {
super.initState();
// 页面渲染完成后,初始化 App 状态(避免阻塞 UI 导致白屏)
WidgetsBinding.instance.addPostFrameCallback((_) {
Provider.of<AppProvider>(context, listen: false).initAppFlag();
});
}
Widget build(BuildContext context) {
// 监听状态变化,动态切换页面
return Consumer<AppProvider>(
builder: (ctx, appProvider, child) {
// 启动页未结束,一直显示启动页
if (!appProvider.splashEnd) {
return const SplashPage();
}
// 启动页结束,判断是否首次打开:首次→引导页,非首次→主页
return appProvider.isFirstOpen ? const GuidePage() : const HomePage();
},
);
}
}
十、项目运行
完整逻辑效果
-
首次安装打开 App:展示 2 秒启动页 → 自动进入引导轮播页

-
引导页可左右滑动,点击「下一页」切换页面,最后一页点击「开始使用」

-
点击「开始使用」后,标记为非首次打开,自动跳转至主页
-
第二次及以后打开 App:启动页展示 2 秒 → 直接进入主页,不再显示引导页
-
重启 App 后,本地存储的「非首次打开」标记不丢失,逻辑正常
10.3 鸿蒙适配核心要点(必看)
-
三方库适配:所有使用的 provider、shared_preferences 均为鸿蒙已适配库,无未适配依赖,避免编译报错
-
白屏优化:本地存储初始化增加 try-catch 异常捕获,避免鸿蒙环境下存储初始化失败导致白屏
-
生命周期安全:使用 WidgetsBinding.instance.addPostFrameCallback 执行初始化,避免阻塞 UI 线程
-
路径规范:项目路径严格为纯英文,避免 hvigor、ohpm 编译时出现文件找不到、路径错误
-
兼容性:界面使用自适应布局,兼容不同尺寸的鸿蒙设备(手机、平板)
十一、常见问题与解决方案(避坑指南)
开发过程中遇到的常见报错,对应解决方案如下,可直接参考:
| 问题现象 | 原因分析 | 解决方案 |
|---|---|---|
| 鸿蒙启动白屏 | 异步存储初始化阻塞 UI 线程,或未做异常捕获 | 在 initAppFlag 方法中增加 try-catch 捕获异常,使用 addPostFrameCallback 延后初始化 |
| 引导页不跳转、按钮点击无反应 | 页面生命周期时机不对,未正确获取 Provider 状态 | 确保 Provider 全局注册,点击事件中使用 listen: false 获取 Provider |
| 第二次打开仍进入引导页 | setNotFirst 方法未执行,或本地存储未成功写入 | 检查引导页最后一页按钮点击逻辑,确保 setNotFirst 方法正常执行 |
| 鸿蒙编译 hvigor 报错 | 项目路径含中文/空格,或缓存损坏 | 将项目移至纯英文路径,执行 flutter clean 清理缓存后重新构建 |
| HomePage 重复定义、import 位置错误 | 语法错误,import 指令写在声明之后,或重复定义类 | 确保 import 指令在文件最顶部,类只定义一次(参考本文第八步的 home_page.dart 代码) |
十二、项目总结
本文基于 Flutter + 鸿蒙化三方库,完整实现了 OpenHarmony 应用的启动页延时、新手轮播引导、首次打开逻辑判断、本地状态持久化整套通用方案。项目结构规范、代码低耦合、无语法错误、无编译报错,可直接移植到任意 Flutter 鸿蒙项目中作为通用模板,无需额外修改。
通过本案例,可快速掌握 Flutter 鸿蒙化开发的核心要点:鸿蒙化三方库的调用、本地存储适配、页面路由跳转、白屏优化等,是 Flutter 三方库鸿蒙化开发非常实用的基础入门案例,适合零基础开发者快速上手 Flutter 鸿蒙应用开发。
更多推荐




所有评论(0)