鸿蒙应用中使用Flutter三方库intro_slider实现美观引导页的实战指南
📑 目录
📖 概述
本教程将详细介绍如何在 Flutter 应用中集成 intro_slider 三方库,实现一个美观的应用引导页,支持左右滑动查看功能介绍,并提供"跳过"按钮快速进入主界面。
✨ 功能特性
详细特性:
- ✅ 支持左右滑动查看多个引导页
- 🎨 可自定义每个引导页的内容、颜色、图片
- ⏭️ 提供"跳过"按钮,快速进入主界面
- 🔄 支持"上一步"和"下一步"导航按钮
- 📍 页面指示器显示当前位置
- 💾 首次使用检测,只在首次启动时显示引导页
- 🎯 平滑的页面过渡动画
📋 前置要求
- Flutter SDK 3.9.2 或更高版本
- Dart SDK 3.9.2 或更高版本
- 基本的 Flutter 开发知识
📦 引入三方库步骤
📝 步骤 1:添加依赖
在 pubspec.yaml 文件的 dependencies 部分添加以下依赖:
dependencies:
flutter:
sdk: flutter
# intro_slider: 引导页滑动组件库
intro_slider: ^3.1.0
# shared_preferences: 本地数据存储库,用于保存首次使用标志
shared_preferences: ^2.2.2
📝 代码解读:
intro_slider: ^3.1.0:引导页滑动组件库,提供左右滑动、页面指示器、导航按钮等功能shared_preferences: ^2.2.2:本地键值存储库,用于保存用户是否首次使用应用的标志
💡 版本说明:
^3.1.0表示使用 3.1.0 或更高版本(但低于 4.0.0)- 使用
^前缀可以自动获取兼容的更新版本
📁 步骤 2:配置资源文件
在 pubspec.yaml 的 flutter 部分添加资源路径(如果还没有添加):
flutter:
uses-material-design: true
assets:
- assets/images/
- assets/animations/
📝 代码解读:
assets/images/:存放引导页图片资源- 如果图片路径不存在,组件会显示占位符,不会导致应用崩溃
📂 步骤 3:创建资源文件夹(可选)
在项目根目录创建以下文件夹结构(如果还没有):
项目根目录/
├── assets/
│ ├── images/
│ │ ├── logo.png # 应用 Logo
│ │ ├── intro_1.png # 引导页第1页图片(可选)
│ │ ├── intro_2.png # 引导页第2页图片(可选)
│ │ ├── intro_3.png # 引导页第3页图片(可选)
│ │ └── intro_4.png # 引导页第4页图片(可选)
│ └── animations/ # 动画资源(可选)
💡 提示:
- 图片资源是可选的,如果不提供图片,组件会正常显示文字内容
- 建议图片尺寸:1080x1920 或 750x1334(适配不同屏幕)
- 图片格式:PNG(支持透明)或 JPG
⬇️ 步骤 4:安装依赖
在终端执行以下命令:
flutter pub get
📝 命令说明:
flutter pub get:下载并安装pubspec.yaml中声明的所有依赖包- 执行成功后,依赖包会被下载到项目的
.dart_tool目录
✅ 验证安装:
安装成功后,可以在 pubspec.lock 文件中看到依赖包的版本信息。
🎨 具体页面实现功能
1️⃣ 创建首选项管理工具类
创建文件 lib/utils/preferences_helper.dart:
// 导入 shared_preferences 三方库,用于本地数据存储
import 'package:shared_preferences/shared_preferences.dart';
// 导入 Flutter 基础库,用于 debugPrint
import 'package:flutter/foundation.dart';
/// 首选项管理工具类
/// 用于管理应用的本地存储数据,如首次使用标志等
class PreferencesHelper {
/// 首次使用标志的键名
/// 用于在 SharedPreferences 中存储和读取是否首次使用应用的标志
static const String _keyIsFirstLaunch = 'is_first_launch';
/// 检查是否首次启动应用
///
/// 返回值:
/// - true: 首次启动,需要显示引导页
/// - false: 非首次启动,直接进入主页面
static Future<bool> isFirstLaunch() async {
try {
// 获取 SharedPreferences 实例
final prefs = await SharedPreferences.getInstance();
// 读取首次启动标志
// getBool: 获取布尔值,如果键不存在则返回 null
// ?? true: 如果返回 null(即键不存在),则默认为 true(首次启动)
final isFirst = prefs.getBool(_keyIsFirstLaunch) ?? true;
return isFirst;
} catch (e) {
// 如果读取失败,默认返回 true,确保用户能看到引导页
debugPrint('读取首次启动标志失败: $e');
return true;
}
}
/// 设置已非首次启动
///
/// 当用户完成引导页或点击跳过时调用此方法
/// 将首次启动标志设置为 false,下次启动时不再显示引导页
static Future<void> setNotFirstLaunch() async {
try {
final prefs = await SharedPreferences.getInstance();
// 设置首次启动标志为 false
await prefs.setBool(_keyIsFirstLaunch, false);
} catch (e) {
debugPrint('保存首次启动标志失败: $e');
}
}
/// 重置首次启动标志(用于测试或重新显示引导页)
static Future<void> resetFirstLaunch() async {
try {
final prefs = await SharedPreferences.getInstance();
await prefs.setBool(_keyIsFirstLaunch, true);
} catch (e) {
debugPrint('重置首次启动标志失败: $e');
}
}
}
📝 代码解读:
SharedPreferences 是什么?
- Flutter 提供的本地键值存储工具
- 数据会持久化保存在设备上,应用重启后仍然存在
- 适合存储简单的配置信息,如用户偏好设置、首次使用标志等
isFirstLaunch() 方法:
详细说明:
getBool(_keyIsFirstLaunch):读取布尔值- 如果键存在,返回对应的布尔值
- 如果键不存在,返回
null
?? true:空值合并运算符- 如果左侧为
null,返回右侧的值(true) - 首次安装应用时,键不存在,返回
true(需要显示引导页)
- 如果左侧为
setNotFirstLaunch() 方法:
setBool(_keyIsFirstLaunch, false):保存布尔值到本地存储- 调用此方法后,下次启动应用时
isFirstLaunch()会返回false
💡 实际应用场景:
代码示例:
// 检查是否首次启动
bool isFirst = await PreferencesHelper.isFirstLaunch();
if (isFirst) {
// 显示引导页
Navigator.push(context, MaterialPageRoute(builder: (_) => IntroScreen()));
} else {
// 直接进入主页面
Navigator.push(context, MaterialPageRoute(builder: (_) => HomePage()));
}
// 用户完成引导后,标记已非首次启动
await PreferencesHelper.setNotFirstLaunch();
2️⃣ 创建引导页组件
创建文件 lib/screens/intro_screen.dart:
// 导入 Flutter Material 设计库,提供 UI 组件和主题
import 'package:flutter/material.dart';
// 导入 intro_slider 三方库,用于实现引导页滑动功能
import 'package:intro_slider/intro_slider.dart';
// 导入 intro_slider 的内容配置类
import 'package:intro_slider/slide_object.dart';
// 导入 intro_slider 的配置类
import 'package:intro_slider/scrollbar_behavior_enum.dart';
/// 引导页组件
/// 用于首次启动应用时展示功能介绍
/// 支持左右滑动查看多个引导页,提供"跳过"按钮快速进入主界面
class IntroScreen extends StatefulWidget {
/// 引导页完成后的回调函数
/// 当用户完成引导或点击跳过时调用,用于跳转到主页面
final VoidCallback onDone;
/// 构造函数
const IntroScreen({
super.key,
required this.onDone,
});
State<IntroScreen> createState() => _IntroScreenState();
}
/// 引导页状态类
/// 管理引导页的配置和交互逻辑
class _IntroScreenState extends State<IntroScreen> {
/// 引导页列表
/// 每个 Slide 对象代表一个引导页
List<Slide> slides = [];
/// Widget 初始化方法
void initState() {
super.initState();
// 初始化引导页内容
_initSlides();
}
/// 初始化引导页内容
/// 创建多个引导页,展示天气预报应用的主要功能
void _initSlides() {
slides = [
// 第一页:欢迎页
Slide(
title: "欢迎使用天气预报",
description: "实时掌握天气变化,为您的生活出行提供精准的天气信息",
pathImage: "assets/images/intro_1.png",
backgroundColor: const Color(0xFF64B5F6), // 浅蓝色
titleColor: Colors.white,
descriptionColor: Colors.white,
directionColorBegin: Alignment.topLeft,
directionColorEnd: Alignment.bottomRight,
),
// 第二页:实时天气功能
Slide(
title: "实时天气查询",
description: "获取当前位置的实时天气状况,包括温度、湿度、风速等详细信息",
pathImage: "assets/images/intro_2.png",
backgroundColor: const Color(0xFF42A5F5), // 蓝色
titleColor: Colors.white,
descriptionColor: Colors.white,
directionColorBegin: Alignment.topLeft,
directionColorEnd: Alignment.bottomRight,
),
// 第三页:多城市管理
Slide(
title: "多城市管理",
description: "添加多个城市,快速切换查看不同地区的天气情况,方便出行规划",
pathImage: "assets/images/intro_3.png",
backgroundColor: const Color(0xFF1E88E5), // 深蓝色
titleColor: Colors.white,
descriptionColor: Colors.white,
directionColorBegin: Alignment.topLeft,
directionColorEnd: Alignment.bottomRight,
),
// 第四页:天气预报
Slide(
title: "未来天气预报",
description: "查看未来7天的天气预报,提前了解天气变化趋势,做好出行准备",
pathImage: "assets/images/intro_4.png",
backgroundColor: const Color(0xFF1565C0), // 更深蓝色
titleColor: Colors.white,
descriptionColor: Colors.white,
directionColorBegin: Alignment.topLeft,
directionColorEnd: Alignment.bottomRight,
),
];
}
/// 构建 Widget 树
Widget build(BuildContext context) {
return IntroSlider(
// slides: 引导页列表
slides: slides,
// onDonePress: 完成按钮点击回调
onDonePress: () {
widget.onDone();
},
// onSkipPress: 跳过按钮点击回调
onSkipPress: () {
widget.onDone();
},
// showSkipBtn: 是否显示跳过按钮
showSkipBtn: true,
// 按钮样式配置
skipButtonStyle: ButtonStyle(
backgroundColor: WidgetStateProperty.all(Colors.white.withOpacity(0.3)),
foregroundColor: WidgetStateProperty.all(Colors.white),
padding: WidgetStateProperty.all(
const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
),
shape: WidgetStateProperty.all(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
),
),
),
// 页面指示器配置
indicatorConfig: IndicatorConfig(
sizeIndicator: 10,
colorIndicator: Colors.white,
colorActiveIndicator: Colors.white.withOpacity(0.5),
typeIndicatorAnimation: TypeIndicatorAnimation.sizeTransition,
),
// 其他配置
scrollbarBehavior: ScrollbarBehavior.HIDE,
hideStatusBar: false,
backgroundColorAllSlides: Colors.blue,
isShowPrevBtn: true,
isShowNextBtn: true,
isShowDoneBtn: true,
);
}
}

📝 代码解读:
Slide 对象属性:
title:页面标题文字description:页面描述文字pathImage:页面背景图片路径(可选)backgroundColor:页面背景颜色titleColor:标题文字颜色descriptionColor:描述文字颜色directionColorBegin/End:渐变方向(如果使用渐变背景)
IntroSlider 主要配置:
配置说明:
slides:引导页列表onDonePress:完成按钮回调(最后一页的"开始使用"按钮)onSkipPress:跳过按钮回调(右上角的"跳过"按钮)showSkipBtn:是否显示跳过按钮indicatorConfig:页面指示器配置(小圆点)isShowPrevBtn:是否显示"上一步"按钮isShowNextBtn:是否显示"下一步"按钮isShowDoneBtn:是否显示"完成"按钮(最后一页)
引导页交互流程:
💡 自定义按钮样式:
// 自定义跳过按钮
renderSkipBtn: () {
return Container(
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
decoration: BoxDecoration(
color: Colors.white.withOpacity(0.3),
borderRadius: BorderRadius.circular(20),
),
child: const Text(
"跳过",
style: TextStyle(
color: Colors.white,
fontSize: 16,
fontWeight: FontWeight.w600,
),
),
);
},
3️⃣ 修改主应用入口
修改文件 lib/main.dart:
// 导入必要的库
import 'package:flutter/material.dart';
import 'package:flutter_splash_screen/flutter_splash_screen.dart';
import 'screens/splash_screen.dart';
import 'screens/intro_screen.dart';
import 'utils/preferences_helper.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
Widget build(BuildContext context) {
return MaterialApp(
title: '天气预报',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
useMaterial3: true,
),
home: const SplashWrapper(),
debugShowCheckedModeBanner: false,
);
}
}
/// 启动页包装器 Widget
/// 负责显示启动页、引导页和主页面的跳转逻辑
class SplashWrapper extends StatefulWidget {
const SplashWrapper({super.key});
State<SplashWrapper> createState() => _SplashWrapperState();
}
/// 启动页包装器的状态类
class _SplashWrapperState extends State<SplashWrapper> {
/// 页面显示状态枚举
enum PageState {
splash, // 显示启动页
intro, // 显示引导页(首次使用)
home, // 显示主页面
}
PageState _pageState = PageState.splash;
void initState() {
super.initState();
_hideNativeSplash();
}
/// 隐藏原生启动屏
Future<void> _hideNativeSplash() async {
await Future.delayed(const Duration(milliseconds: 100));
if (mounted) {
await FlutterSplashScreen.hide();
}
}
/// 启动页完成回调函数
/// 检查是否首次使用,决定显示引导页还是主页面
void _onSplashComplete() async {
if (!mounted) return;
// 检查是否首次启动应用
final isFirst = await PreferencesHelper.isFirstLaunch();
if (mounted) {
setState(() {
if (isFirst) {
// 首次启动,显示引导页
_pageState = PageState.intro;
} else {
// 非首次启动,直接显示主页面
_pageState = PageState.home;
}
});
}
}
/// 引导页完成回调函数
/// 标记已非首次启动,并跳转到主页面
void _onIntroComplete() async {
// 标记已非首次启动
await PreferencesHelper.setNotFirstLaunch();
if (mounted) {
setState(() {
_pageState = PageState.home;
});
}
}
/// 构建 Widget 树
Widget build(BuildContext context) {
switch (_pageState) {
case PageState.splash:
// 显示启动页
return SplashScreen(
duration: 2000,
enableAnimation: true,
logoPath: 'assets/images/logo.png',
onComplete: _onSplashComplete,
);
case PageState.intro:
// 显示引导页(首次使用)
return IntroScreen(
onDone: _onIntroComplete,
);
case PageState.home:
// 显示主页面
return const MyHomePage(title: '天气预报');
}
}
}
📝 代码解读:
页面流程:
详细步骤:
- 启动页(Splash):应用启动时显示,持续 2 秒
- 检查首次使用:启动页完成后,调用
PreferencesHelper.isFirstLaunch()检查 - 引导页(Intro):如果是首次使用,显示引导页
- 主页面(Home):如果不是首次使用,或引导页完成后,显示主页面
状态管理:
状态切换机制:
- 使用
PageState枚举管理页面状态 - 通过
setState()切换页面状态 - 使用
mounted检查确保 Widget 仍然存在
💡 流程说明:
⚠️ 常见错误及解决方案
❌ 错误 1:依赖安装失败
错误信息:
Running "flutter pub get" in ffohnotes...
pub get failed
可能原因:
- 网络连接问题
pubspec.yaml语法错误- Flutter SDK 版本不兼容
解决方案:
# 1. 检查网络连接
ping pub.dev
# 2. 清理缓存后重新安装
flutter clean
flutter pub get
# 3. 检查 pubspec.yaml 语法
# 确保缩进正确(使用空格,不要使用 Tab)
# 确保版本号格式正确(如 ^3.1.0)
# 4. 使用国内镜像(如果网络较慢)
export PUB_HOSTED_URL=https://pub.flutter-io.cn
export FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn
flutter pub get
❌ 错误 2:图片资源找不到
错误信息:
Unable to load asset: assets/images/intro_1.png
可能原因:
- 图片文件不存在
pubspec.yaml中未配置资源路径- 图片路径拼写错误
解决方案:
// 方案1:检查图片是否存在
// 确保 assets/images/intro_1.png 文件存在
// 方案2:在 pubspec.yaml 中配置资源路径
flutter:
assets:
- assets/images/
// 方案3:使用占位符(推荐)
// intro_slider 会自动处理图片加载失败的情况
// 如果图片不存在,会显示占位符,不会导致应用崩溃
// 方案4:不提供图片路径(可选)
Slide(
title: "欢迎使用天气预报",
description: "实时掌握天气变化...",
// pathImage: "assets/images/intro_1.png", // 注释掉或删除
backgroundColor: const Color(0xFF64B5F6),
// ...
)
❌ 错误 3:SharedPreferences 初始化失败
错误信息:
PlatformException(channel-error, Unable to establish connection on channel., null, null)
可能原因:
- 平台特定配置缺失(Android/iOS)
- 权限问题
解决方案:
Android 配置(android/app/src/main/AndroidManifest.xml):
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 添加存储权限(如果需要) -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<application
android:label="天气预报"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher">
<!-- ... -->
</application>
</manifest>
iOS 配置(通常不需要额外配置):
shared_preferences在 iOS 上使用UserDefaults,通常不需要额外权限
错误处理:
static Future<bool> isFirstLaunch() async {
try {
final prefs = await SharedPreferences.getInstance();
return prefs.getBool(_keyIsFirstLaunch) ?? true;
} catch (e) {
// 如果初始化失败,返回 true(显示引导页)
debugPrint('SharedPreferences 初始化失败: $e');
return true;
}
}
❌ 错误 4:引导页不显示
错误信息:
- 应用启动后直接进入主页面,没有显示引导页
问题诊断流程:
可能原因:
PreferencesHelper.isFirstLaunch()返回false- 引导页组件未正确集成
- 状态管理问题
解决方案:
// 1. 检查首次使用标志
// 在调试时,可以重置标志来测试引导页
await PreferencesHelper.resetFirstLaunch();
// 2. 添加调试日志
void _onSplashComplete() async {
if (!mounted) return;
final isFirst = await PreferencesHelper.isFirstLaunch();
debugPrint('是否首次启动: $isFirst'); // 添加日志
if (mounted) {
setState(() {
if (isFirst) {
_pageState = PageState.intro;
debugPrint('切换到引导页'); // 添加日志
} else {
_pageState = PageState.home;
debugPrint('切换到主页面'); // 添加日志
}
});
}
}
// 3. 检查引导页组件是否正确导入
import 'screens/intro_screen.dart';
// 4. 确保 IntroScreen 组件正确创建
case PageState.intro:
return IntroScreen(
onDone: _onIntroComplete, // 确保回调函数正确传递
);
❌ 错误 5:按钮点击无响应
错误信息:
- 点击"跳过"或"开始使用"按钮没有反应
问题排查流程:
可能原因:
- 回调函数未正确传递
onDone回调函数为空或未实现
解决方案:
// 1. 检查回调函数是否正确传递
IntroScreen(
onDone: _onIntroComplete, // 确保传递了回调函数
)
// 2. 确保回调函数已实现
void _onIntroComplete() async {
debugPrint('引导页完成回调被调用'); // 添加日志验证
await PreferencesHelper.setNotFirstLaunch();
if (mounted) {
setState(() {
_pageState = PageState.home;
});
}
}
// 3. 检查 IntroScreen 内部是否正确调用回调
onDonePress: () {
widget.onDone(); // 确保调用了外部传入的回调
},
onSkipPress: () {
widget.onDone(); // 确保调用了外部传入的回调
},
❌ 错误 6:页面指示器不显示
错误信息:
- 引导页底部没有显示页面指示器(小圆点)
可能原因:
indicatorConfig配置错误- 颜色设置与背景色相同,导致看不见
解决方案:
// 1. 检查指示器配置
indicatorConfig: IndicatorConfig(
sizeIndicator: 10, // 确保大小不为 0
colorIndicator: Colors.white, // 确保颜色与背景色不同
colorActiveIndicator: Colors.white.withOpacity(0.5),
typeIndicatorAnimation: TypeIndicatorAnimation.sizeTransition,
),
// 2. 如果背景是白色,使用深色指示器
indicatorConfig: IndicatorConfig(
sizeIndicator: 10,
colorIndicator: Colors.blue, // 使用深色
colorActiveIndicator: Colors.blue.withOpacity(0.5),
typeIndicatorAnimation: TypeIndicatorAnimation.sizeTransition,
),
❌ 错误 7:滑动不流畅
错误信息:
- 左右滑动引导页时卡顿或不流畅
可能原因:
- 图片过大
- 动画效果过多
- 设备性能问题
解决方案:
// 1. 优化图片大小
// 建议图片尺寸:1080x1920 或 750x1334
// 使用图片压缩工具减小文件大小
// 2. 减少动画效果
indicatorConfig: IndicatorConfig(
typeIndicatorAnimation: TypeIndicatorAnimation.none, // 禁用动画
),
// 3. 使用占位符代替大图片
// 如果图片加载慢,可以先显示占位符
Slide(
title: "欢迎使用天气预报",
description: "实时掌握天气变化...",
// pathImage: "assets/images/intro_1.png", // 不提供图片
backgroundColor: const Color(0xFF64B5F6),
// ...
)
🔧 进阶功能
1️⃣ 自定义引导页样式
自定义按钮样式:
IntroSlider(
slides: slides,
// 自定义跳过按钮
renderSkipBtn: () {
return Container(
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
decoration: BoxDecoration(
color: Colors.white.withOpacity(0.3),
borderRadius: BorderRadius.circular(20),
border: Border.all(color: Colors.white, width: 2),
),
child: const Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(Icons.close, color: Colors.white, size: 18),
SizedBox(width: 4),
Text(
"跳过",
style: TextStyle(
color: Colors.white,
fontSize: 16,
fontWeight: FontWeight.w600,
),
),
],
),
);
},
// 自定义完成按钮
renderDoneBtn: () {
return Container(
padding: const EdgeInsets.symmetric(horizontal: 30, vertical: 12),
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Colors.white, Colors.blue.shade100],
),
borderRadius: BorderRadius.circular(25),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.2),
blurRadius: 8,
offset: const Offset(0, 4),
),
],
),
child: const Row(
mainAxisSize: MainAxisSize.min,
children: [
Text(
"开始使用",
style: TextStyle(
color: Color(0xFF1565C0),
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
SizedBox(width: 8),
Icon(Icons.arrow_forward, color: Color(0xFF1565C0), size: 20),
],
),
);
},
)
自定义页面布局:
// 使用自定义 Widget 构建页面内容
Slide(
title: "欢迎使用天气预报",
description: "实时掌握天气变化...",
// 使用自定义 Widget
widgetDescription: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.wb_sunny, size: 100, color: Colors.white),
const SizedBox(height: 20),
const Text(
"欢迎使用天气预报",
style: TextStyle(
fontSize: 28,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
const SizedBox(height: 16),
const Text(
"实时掌握天气变化,为您的生活出行提供精准的天气信息",
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 16,
color: Colors.white,
),
),
],
),
backgroundColor: const Color(0xFF64B5F6),
)
2️⃣ 添加页面切换动画
IntroSlider(
slides: slides,
// 页面切换动画配置
animationDuration: const Duration(milliseconds: 300),
// 滑动方向(水平或垂直)
verticalScrollbarBehavior: ScrollbarBehavior.HIDE,
)
3️⃣ 根据设备语言显示不同内容
void _initSlides() {
// 获取设备语言
final locale = Localizations.localeOf(context);
final isChinese = locale.languageCode == 'zh';
slides = [
Slide(
title: isChinese ? "欢迎使用天气预报" : "Welcome to Weather App",
description: isChinese
? "实时掌握天气变化,为您的生活出行提供精准的天气信息"
: "Get real-time weather updates for your daily life and travel",
backgroundColor: const Color(0xFF64B5F6),
titleColor: Colors.white,
descriptionColor: Colors.white,
),
// ... 其他页面
];
}
4️⃣ 添加页面切换监听
IntroSlider(
slides: slides,
// 页面切换回调
onTabChangeCompleted: (index) {
debugPrint('切换到第 ${index + 1} 页');
// 可以在这里添加页面切换动画、统计等
},
)
5️⃣ 条件显示引导页
版本更新检测流程:
代码实现:
// 根据应用版本决定是否显示引导页
Future<bool> shouldShowIntro() async {
final prefs = await SharedPreferences.getInstance();
final lastVersion = prefs.getString('last_intro_version');
final currentVersion = '1.0.0'; // 从 package_info_plus 获取
// 如果版本更新,重新显示引导页
if (lastVersion != currentVersion) {
await prefs.setString('last_intro_version', currentVersion);
return true;
}
// 检查是否首次启动
return prefs.getBool('is_first_launch') ?? true;
}
📚 完整代码示例
文件结构
目录说明:
lib/
├── main.dart # 应用入口
├── screens/
│ ├── splash_screen.dart # 启动页
│ └── intro_screen.dart # 引导页
└── utils/
└── preferences_helper.dart # 首选项管理工具
完整代码
所有代码文件已在前面章节提供,这里不再重复。完整的项目代码包括:
lib/utils/preferences_helper.dart:首选项管理工具类lib/screens/intro_screen.dart:引导页组件lib/main.dart:主应用入口(已修改)
运行项目
# 1. 安装依赖
flutter pub get
# 2. 运行应用
flutter run
# 3. 测试引导页
# 首次运行会显示引导页
# 完成引导后,再次运行不会显示引导页
# 4. 重置引导页(用于测试)
# 在代码中调用:
await PreferencesHelper.resetFirstLaunch();
📖 总结
本教程详细介绍了如何使用 intro_slider 三方库实现 Flutter 应用引导页,包括:
✅ 引入三方库步骤:添加依赖、配置资源、安装依赖
✅ 具体页面实现:创建工具类、引导页组件、集成到主应用
✅ 常见错误解决:依赖安装、资源加载、状态管理等问题
✅ 进阶功能:自定义样式、多语言支持、条件显示等
🎯 关键要点
- 首次使用检测:使用
SharedPreferences保存首次使用标志 - 页面状态管理:使用枚举管理启动页、引导页、主页面的切换
- 用户体验:提供"跳过"按钮,允许用户快速进入主界面
- 错误处理:添加异常处理,确保应用稳定运行
📚 相关资源
🎉 祝你开发顺利! 🚀
更多推荐



所有评论(0)