feat(mobile-app): 开屏页改为随机静态图片模式
- 禁用帧动画,改为显示随机静态图片(3张中随机选1张) - 显示3秒后自动跳转,保留跳过按钮 - 帧动画代码保留备用,可通过 _useStaticImage 开关切换 - 新增 splash_static 目录存放静态图片 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
fabfbb73fe
commit
414fe95d04
Binary file not shown.
|
After Width: | Height: | Size: 1.5 MiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.9 MiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.4 MiB |
|
|
@ -1,3 +1,4 @@
|
|||
import 'dart:math';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
|
@ -10,7 +11,7 @@ import '../../../../routes/app_router.dart';
|
|||
import '../providers/auth_provider.dart';
|
||||
|
||||
/// 开屏页面 - 应用启动时显示的第一个页面
|
||||
/// 播放帧动画,动画结束后检查用户认证状态并跳转
|
||||
/// 随机显示一张静态图片,3秒后自动跳转
|
||||
class SplashPage extends ConsumerStatefulWidget {
|
||||
const SplashPage({super.key});
|
||||
|
||||
|
|
@ -19,6 +20,22 @@ class SplashPage extends ConsumerStatefulWidget {
|
|||
}
|
||||
|
||||
class _SplashPageState extends ConsumerState<SplashPage> {
|
||||
// ========== 静态图片模式配置 ==========
|
||||
|
||||
/// 是否使用静态图片模式(false = 使用帧动画)
|
||||
static const bool _useStaticImage = true;
|
||||
|
||||
/// 静态图片显示时长(秒)
|
||||
static const int _staticDisplaySeconds = 3;
|
||||
|
||||
/// 静态图片数量
|
||||
static const int _staticImageCount = 3;
|
||||
|
||||
/// 当前显示的静态图片索引 (1-based)
|
||||
late int _staticImageIndex;
|
||||
|
||||
// ========== 帧动画模式配置(保留备用) ==========
|
||||
|
||||
/// 帧动画总帧数
|
||||
static const int _totalFrames = 36;
|
||||
|
||||
|
|
@ -28,25 +45,55 @@ class _SplashPageState extends ConsumerState<SplashPage> {
|
|||
/// 当前显示的帧索引 (0-based)
|
||||
int _currentFrameIndex = 0;
|
||||
|
||||
/// 预加载的图片缓存(帧动画用)
|
||||
final List<ImageProvider> _frameProviders = [];
|
||||
|
||||
// ========== 通用状态 ==========
|
||||
|
||||
/// 是否显示跳过按钮
|
||||
bool _showSkipButton = false;
|
||||
|
||||
/// 是否已经开始跳转(防止重复跳转)
|
||||
bool _isNavigating = false;
|
||||
|
||||
/// 帧动画是否正在播放
|
||||
/// 动画/计时器是否正在运行
|
||||
bool _isPlaying = true;
|
||||
|
||||
/// 预加载的图片缓存
|
||||
final List<ImageProvider> _frameProviders = [];
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_initializeFrames();
|
||||
|
||||
if (_useStaticImage) {
|
||||
_initializeStaticImage();
|
||||
} else {
|
||||
_initializeFrames();
|
||||
}
|
||||
}
|
||||
|
||||
/// 初始化帧动画
|
||||
/// 初始化静态图片模式
|
||||
void _initializeStaticImage() {
|
||||
// 随机选择一张图片 (1 到 _staticImageCount)
|
||||
_staticImageIndex = Random().nextInt(_staticImageCount) + 1;
|
||||
debugPrint('[SplashPage] 静态图片模式:显示 splash_$_staticImageIndex.jpg');
|
||||
|
||||
// 3秒后自动跳转
|
||||
Future.delayed(Duration(seconds: _staticDisplaySeconds), () {
|
||||
if (mounted && _isPlaying) {
|
||||
_navigateToNextPage();
|
||||
}
|
||||
});
|
||||
|
||||
// 1秒后显示跳过按钮
|
||||
Future.delayed(const Duration(seconds: 1), () {
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_showSkipButton = true;
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// 初始化帧动画(保留备用)
|
||||
void _initializeFrames() {
|
||||
// 创建所有帧的 ImageProvider(不会立即加载,只是创建引用)
|
||||
for (int i = 1; i <= _totalFrames; i++) {
|
||||
|
|
@ -71,11 +118,20 @@ class _SplashPageState extends ConsumerState<SplashPage> {
|
|||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
// 预加载前几帧到内存,确保播放流畅
|
||||
_precacheInitialFrames();
|
||||
|
||||
if (_useStaticImage) {
|
||||
// 预加载静态图片
|
||||
precacheImage(
|
||||
AssetImage('assets/images/splash_static/splash_$_staticImageIndex.jpg'),
|
||||
context,
|
||||
);
|
||||
} else {
|
||||
// 预加载前几帧到内存,确保播放流畅
|
||||
_precacheInitialFrames();
|
||||
}
|
||||
}
|
||||
|
||||
/// 预加载前几帧
|
||||
/// 预加载前几帧(帧动画用)
|
||||
void _precacheInitialFrames() {
|
||||
// 预加载前5帧,确保启动时不卡顿
|
||||
final framesToPrecache = _totalFrames < 5 ? _totalFrames : 5;
|
||||
|
|
@ -84,7 +140,7 @@ class _SplashPageState extends ConsumerState<SplashPage> {
|
|||
}
|
||||
}
|
||||
|
||||
/// 播放帧动画
|
||||
/// 播放帧动画(保留备用)
|
||||
Future<void> _playAnimation() async {
|
||||
final frameDuration = Duration(milliseconds: 1000 ~/ _frameRate);
|
||||
|
||||
|
|
@ -110,7 +166,7 @@ class _SplashPageState extends ConsumerState<SplashPage> {
|
|||
}
|
||||
}
|
||||
|
||||
/// 跳过动画
|
||||
/// 跳过动画/等待
|
||||
void _skipAnimation() {
|
||||
_isPlaying = false;
|
||||
_navigateToNextPage();
|
||||
|
|
@ -222,8 +278,8 @@ class _SplashPageState extends ConsumerState<SplashPage> {
|
|||
body: Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
// 帧动画(全屏覆盖)
|
||||
_buildFrameAnimation(),
|
||||
// 启动图片/动画(全屏覆盖)
|
||||
_useStaticImage ? _buildStaticImage() : _buildFrameAnimation(),
|
||||
|
||||
// 跳过按钮
|
||||
if (_showSkipButton)
|
||||
|
|
@ -237,7 +293,17 @@ class _SplashPageState extends ConsumerState<SplashPage> {
|
|||
);
|
||||
}
|
||||
|
||||
/// 构建帧动画视图
|
||||
/// 构建静态图片视图
|
||||
Widget _buildStaticImage() {
|
||||
return SizedBox.expand(
|
||||
child: Image.asset(
|
||||
'assets/images/splash_static/splash_$_staticImageIndex.jpg',
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// 构建帧动画视图(保留备用)
|
||||
Widget _buildFrameAnimation() {
|
||||
return SizedBox.expand(
|
||||
child: Image(
|
||||
|
|
|
|||
|
|
@ -109,6 +109,7 @@ flutter:
|
|||
- assets/images/avatars/
|
||||
- assets/images/illustrations/
|
||||
- assets/images/splash_frames/
|
||||
- assets/images/splash_static/
|
||||
- assets/icons/
|
||||
- assets/icons/nav/
|
||||
- assets/icons/tokens/
|
||||
|
|
|
|||
Loading…
Reference in New Issue