You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Flutter中实现可存储数据、含不同模型的引导页?

实现可存储数据的多模型Flutter引导页

核心思路

这类引导页需要满足三个核心需求:首次启动展示、支持多样化引导内容、记录用户是否完成引导。下面分步骤实现:


1. 实现引导状态存储

用shared_preferences包存储用户是否已查看引导页的状态,这是轻量化且易实现的方案。

首先在pubspec.yaml添加依赖:

dependencies:
  shared_preferences: ^2.2.2

封装工具类处理存储逻辑:

import 'package:shared_preferences/shared_preferences.dart';

class OnboardingPrefs {
  static const _keyHasCompleted = 'onboarding_completed';

  // 检查是否已完成引导
  static Future<bool> hasCompletedOnboarding() async {
    final prefs = await SharedPreferences.getInstance();
    return prefs.getBool(_keyHasCompleted) ?? false;
  }

  // 标记引导完成
  static Future<void> markOnboardingCompleted() async {
    final prefs = await SharedPreferences.getInstance();
    await prefs.setBool(_keyHasCompleted, true);
  }
}

在App启动时判断是否展示引导页:

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  final hasCompleted = await OnboardingPrefs.hasCompletedOnboarding();
  runApp(MyApp(showOnboarding: !hasCompleted));
}

class MyApp extends StatelessWidget {
  final bool showOnboarding;

  const MyApp({super.key, required this.showOnboarding});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: showOnboarding ? const OnboardingScreen() : const HomeScreen(),
    );
  }
}

2. 多模型引导页实现

先定义引导页的数据模型,支持不同的标题、描述、图片和背景色,轻松扩展不同样式的引导页:

class OnboardingPageModel {
  final String title;
  final String description;
  final String imagePath;
  final Color bgColor;

  OnboardingPageModel({
    required this.title,
    required this.description,
    required this.imagePath,
    required this.bgColor,
  });
}

准备多组引导数据(示例3个不同模型的引导页):

final List<OnboardingPageModel> onboardingPages = [
  OnboardingPageModel(
    title: '欢迎使用',
    description: '开启你的专属应用之旅,探索更多功能',
    imagePath: 'assets/onboard_welcome.png',
    bgColor: Colors.lightBlue.shade100,
  ),
  OnboardingPageModel(
    title: '智能管理',
    description: '一键整理你的所有数据,高效又省心',
    imagePath: 'assets/onboard_manage.png',
    bgColor: Colors.lightGreen.shade100,
  ),
  OnboardingPageModel(
    title: '云端同步',
    description: '数据实时同步,再也不用担心丢失',
    imagePath: 'assets/onboard_sync.png',
    bgColor: Colors.orange.shade100,
  ),
];

用PageView实现引导页的滑动切换UI:

class OnboardingScreen extends StatefulWidget {
  const OnboardingScreen({super.key});

  @override
  State<OnboardingScreen> createState() => _OnboardingScreenState();
}

class _OnboardingScreenState extends State<OnboardingScreen> {
  final PageController _pageController = PageController();
  int _currentIndex = 0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Stack(
        children: [
          // 引导页内容区域
          PageView.builder(
            controller: _pageController,
            itemCount: onboardingPages.length,
            onPageChanged: (index) => setState(() => _currentIndex = index),
            itemBuilder: (context, index) {
              final page = onboardingPages[index];
              return Container(
                color: page.bgColor,
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    Image.asset(page.imagePath, height: 260),
                    const SizedBox(height: 48),
                    Text(
                      page.title,
                      style: const TextStyle(fontSize: 26, fontWeight: FontWeight.w700),
                    ),
                    const SizedBox(height: 16),
                    Padding(
                      padding: const EdgeInsets.symmetric(horizontal: 36),
                      child: Text(
                        page.description,
                        textAlign: TextAlign.center,
                        style: const TextStyle(fontSize: 16, color: Colors.grey),
                      ),
                    ),
                  ],
                ),
              );
            },
          ),
          // 底部操作栏
          Positioned(
            bottom: 40,
            left: 32,
            right: 32,
            child: Column(
              children: [
                // 页面指示器
                Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: List.generate(onboardingPages.length, (index) {
                    return Container(
                      width: _currentIndex == index ? 18 : 8,
                      height: 8,
                      margin: const EdgeInsets.symmetric(horizontal: 4),
                      decoration: BoxDecoration(
                        borderRadius: BorderRadius.circular(4),
                        color: _currentIndex == index ? Colors.blue : Colors.grey.shade300,
                      ),
                    );
                  }),
                ),
                const SizedBox(height: 28),
                // 跳过/下一步/完成按钮
                Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  children: [
                    TextButton(
                      onPressed: () => _completeOnboarding(),
                      child: const Text('跳过', style: TextStyle(color: Colors.grey)),
                    ),
                    ElevatedButton(
                      onPressed: _currentIndex == onboardingPages.length - 1 
                          ? _completeOnboarding 
                          : () => _pageController.nextPage(
                                duration: const Duration(milliseconds: 300),
                                curve: Curves.easeInOut,
                              ),
                      style: ElevatedButton.styleFrom(
                        padding: const EdgeInsets.symmetric(horizontal: 32, vertical: 12),
                        shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
                      ),
                      child: Text(_currentIndex == onboardingPages.length - 1 ? '完成' : '下一步'),
                    ),
                  ],
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }

  // 完成引导,跳转到首页
  void _completeOnboarding() async {
    await OnboardingPrefs.markOnboardingCompleted();
    if (mounted) {
      Navigator.pushReplacement(
        context,
        MaterialPageRoute(builder: (_) => const HomeScreen()),
      );
    }
  }
}

3. 扩展优化建议

  • 自定义动画:给页面切换添加渐入渐出、缩放等动画,通过AnimatedBuilder监听PageController的page值实现
  • 多类型引导页:如果需要带输入框、交互按钮的复杂引导模块,可定义抽象类OnboardingWidget,不同模型对应不同的Widget实现
  • 存储用户偏好:若引导页需收集用户设置(如主题、语言),可扩展OnboardingPrefs存储更多键值对

内容的提问来源于stack exchange,提问作者Yash Deshmukh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 04:15:44