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

Flutter实现Onboarding Screen仅首次显示且Splash Screen每次显示求助

问题修复方案

问题分析

  1. SharedPreferences键名不一致:Onboarding中存储用的是'onBoard',但main中读取用的是'onboard',大小写差异导致无法正确读取状态。
  2. 未传递状态到SplashScreen:main中获取了isViewed但没有传给SplashScreen,导致Splash无法判断是否需要跳转Onboarding。
  3. SplashScreen跳转逻辑缺失判断:动画完成后直接固定跳Onboarding,没有根据用户是否看过Onboarding做分支处理。

修复步骤

1. 统一键名并传递状态到MyApp

修改main.dart,将读取到的状态传递给SplashScreen,同时统一SharedPreferences的键名:

int? isViewed;
Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();

  final prefs = await SharedPreferences.getInstance();
  final showLogin = prefs.getBool('showLogin') ?? false;
  Paint.enableDithering = true;
  await Firebase.initializeApp();

  // 统一键名为'onboard_viewed',避免大小写问题
  isViewed = prefs.getInt('onboard_viewed');

  runApp(MyApp(showLogin: showLogin, isViewed: isViewed));
}

class MyApp extends StatelessWidget {
  final bool showLogin;
  final int? isViewed;

  const MyApp({
    Key? key,
    required this.showLogin,
    required this.isViewed,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Strength',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        appBarTheme: const AppBarTheme(
          color: Colors.white,
          elevation: 0,
          brightness: Brightness.light,
          iconTheme: IconThemeData(color: Colors.black),
          textTheme: TextTheme(
            headline6: TextStyle(color: Color(0xff888888), fontSize: 18),
          ),
        ),
      ),
      home: SplashScreen(showLogin: showLogin, isViewed: isViewed),
    );
  }
}

2. 更新OnboardingScreen的存储键名

修改_storeOnboardingInfo方法,使用统一的键名:

_storeOnboardingInfo() async {
  int isViewed = 0;
  SharedPreferences prefs = await SharedPreferences.getInstance();
  // 与main中统一的键名保持一致
  await prefs.setInt('onboard_viewed', isViewed);
}

3. 修改SplashScreen的跳转逻辑

让SplashScreen接收参数,并根据用户是否看过Onboarding决定跳转目标:

class SplashScreen extends StatefulWidget {
  final bool showLogin;
  final int? isViewed;

  const SplashScreen({
    Key? key,
    required this.showLogin,
    required this.isViewed,
  }) : super(key: key);

  @override
  _SplashScreenState createState() => _SplashScreenState();
}

class _SplashScreenState extends State<SplashScreen> with TickerProviderStateMixin {
  late AnimationController _screenController;

  @override
  void initState() {
    super.initState();
    _screenController = AnimationController(vsync: this);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(
        height: double.infinity,
        width: double.infinity,
        child: Lottie.asset(
          'assets/lottie/splashScreen.lottie.json',
          fit: BoxFit.fill,
          controller: _screenController,
          onLoaded: (composition) {
            _screenController
              ..duration = composition.duration
              ..forward().whenComplete(() {
                // 判断逻辑:已看过Onboarding则跳Landing,否则跳Onboarding
                Widget targetScreen = widget.isViewed != null 
                    ? LandingScreen() 
                    : const OnboardingScreen();

                Navigator.of(context).pushReplacement(
                  PageTransition(
                    type: PageTransitionType.fade,
                    duration: const Duration(milliseconds: 1800),
                    child: targetScreen,
                  ),
                );
              });
          },
        ),
      ),
    );
  }
}

逻辑说明

  • 首次启动:isViewed为null,Splash动画结束后跳转到OnboardingScreen;用户点击"Get Started"后,存储onboard_viewed状态并跳转到LandingScreen。
  • 非首次启动:isViewed存在(值为0),Splash动画结束后直接跳转到LandingScreen,不再显示Onboarding。

内容的提问来源于stack exchange,提问作者Ta-Ty

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 21:10:48