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/material.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
|
|
@ -10,7 +11,7 @@ import '../../../../routes/app_router.dart';
|
||||||
import '../providers/auth_provider.dart';
|
import '../providers/auth_provider.dart';
|
||||||
|
|
||||||
/// 开屏页面 - 应用启动时显示的第一个页面
|
/// 开屏页面 - 应用启动时显示的第一个页面
|
||||||
/// 播放帧动画,动画结束后检查用户认证状态并跳转
|
/// 随机显示一张静态图片,3秒后自动跳转
|
||||||
class SplashPage extends ConsumerStatefulWidget {
|
class SplashPage extends ConsumerStatefulWidget {
|
||||||
const SplashPage({super.key});
|
const SplashPage({super.key});
|
||||||
|
|
||||||
|
|
@ -19,6 +20,22 @@ class SplashPage extends ConsumerStatefulWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
class _SplashPageState extends ConsumerState<SplashPage> {
|
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;
|
static const int _totalFrames = 36;
|
||||||
|
|
||||||
|
|
@ -28,25 +45,55 @@ class _SplashPageState extends ConsumerState<SplashPage> {
|
||||||
/// 当前显示的帧索引 (0-based)
|
/// 当前显示的帧索引 (0-based)
|
||||||
int _currentFrameIndex = 0;
|
int _currentFrameIndex = 0;
|
||||||
|
|
||||||
|
/// 预加载的图片缓存(帧动画用)
|
||||||
|
final List<ImageProvider> _frameProviders = [];
|
||||||
|
|
||||||
|
// ========== 通用状态 ==========
|
||||||
|
|
||||||
/// 是否显示跳过按钮
|
/// 是否显示跳过按钮
|
||||||
bool _showSkipButton = false;
|
bool _showSkipButton = false;
|
||||||
|
|
||||||
/// 是否已经开始跳转(防止重复跳转)
|
/// 是否已经开始跳转(防止重复跳转)
|
||||||
bool _isNavigating = false;
|
bool _isNavigating = false;
|
||||||
|
|
||||||
/// 帧动画是否正在播放
|
/// 动画/计时器是否正在运行
|
||||||
bool _isPlaying = true;
|
bool _isPlaying = true;
|
||||||
|
|
||||||
/// 预加载的图片缓存
|
|
||||||
final List<ImageProvider> _frameProviders = [];
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.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() {
|
void _initializeFrames() {
|
||||||
// 创建所有帧的 ImageProvider(不会立即加载,只是创建引用)
|
// 创建所有帧的 ImageProvider(不会立即加载,只是创建引用)
|
||||||
for (int i = 1; i <= _totalFrames; i++) {
|
for (int i = 1; i <= _totalFrames; i++) {
|
||||||
|
|
@ -71,11 +118,20 @@ class _SplashPageState extends ConsumerState<SplashPage> {
|
||||||
@override
|
@override
|
||||||
void didChangeDependencies() {
|
void didChangeDependencies() {
|
||||||
super.didChangeDependencies();
|
super.didChangeDependencies();
|
||||||
// 预加载前几帧到内存,确保播放流畅
|
|
||||||
_precacheInitialFrames();
|
if (_useStaticImage) {
|
||||||
|
// 预加载静态图片
|
||||||
|
precacheImage(
|
||||||
|
AssetImage('assets/images/splash_static/splash_$_staticImageIndex.jpg'),
|
||||||
|
context,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// 预加载前几帧到内存,确保播放流畅
|
||||||
|
_precacheInitialFrames();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 预加载前几帧
|
/// 预加载前几帧(帧动画用)
|
||||||
void _precacheInitialFrames() {
|
void _precacheInitialFrames() {
|
||||||
// 预加载前5帧,确保启动时不卡顿
|
// 预加载前5帧,确保启动时不卡顿
|
||||||
final framesToPrecache = _totalFrames < 5 ? _totalFrames : 5;
|
final framesToPrecache = _totalFrames < 5 ? _totalFrames : 5;
|
||||||
|
|
@ -84,7 +140,7 @@ class _SplashPageState extends ConsumerState<SplashPage> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 播放帧动画
|
/// 播放帧动画(保留备用)
|
||||||
Future<void> _playAnimation() async {
|
Future<void> _playAnimation() async {
|
||||||
final frameDuration = Duration(milliseconds: 1000 ~/ _frameRate);
|
final frameDuration = Duration(milliseconds: 1000 ~/ _frameRate);
|
||||||
|
|
||||||
|
|
@ -110,7 +166,7 @@ class _SplashPageState extends ConsumerState<SplashPage> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 跳过动画
|
/// 跳过动画/等待
|
||||||
void _skipAnimation() {
|
void _skipAnimation() {
|
||||||
_isPlaying = false;
|
_isPlaying = false;
|
||||||
_navigateToNextPage();
|
_navigateToNextPage();
|
||||||
|
|
@ -222,8 +278,8 @@ class _SplashPageState extends ConsumerState<SplashPage> {
|
||||||
body: Stack(
|
body: Stack(
|
||||||
fit: StackFit.expand,
|
fit: StackFit.expand,
|
||||||
children: [
|
children: [
|
||||||
// 帧动画(全屏覆盖)
|
// 启动图片/动画(全屏覆盖)
|
||||||
_buildFrameAnimation(),
|
_useStaticImage ? _buildStaticImage() : _buildFrameAnimation(),
|
||||||
|
|
||||||
// 跳过按钮
|
// 跳过按钮
|
||||||
if (_showSkipButton)
|
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() {
|
Widget _buildFrameAnimation() {
|
||||||
return SizedBox.expand(
|
return SizedBox.expand(
|
||||||
child: Image(
|
child: Image(
|
||||||
|
|
|
||||||
|
|
@ -109,6 +109,7 @@ flutter:
|
||||||
- assets/images/avatars/
|
- assets/images/avatars/
|
||||||
- assets/images/illustrations/
|
- assets/images/illustrations/
|
||||||
- assets/images/splash_frames/
|
- assets/images/splash_frames/
|
||||||
|
- assets/images/splash_static/
|
||||||
- assets/icons/
|
- assets/icons/
|
||||||
- assets/icons/nav/
|
- assets/icons/nav/
|
||||||
- assets/icons/tokens/
|
- assets/icons/tokens/
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue