feat: 添加启动屏幕图像和主题样式;优化 H5 壳的封面隐藏逻辑

This commit is contained in:
Booker
2026-05-26 22:48:47 +07:00
parent bd3ccf7f2d
commit bb720b227e
12 changed files with 93 additions and 4 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

View File

@@ -9,4 +9,12 @@
android:endColor="#FFFFFF" />
</shape>
</item>
<item
android:width="220dp"
android:height="260dp"
android:gravity="center">
<bitmap
android:gravity="fill"
android:src="@drawable/splash_content" />
</item>
</layer-list>

View File

@@ -9,4 +9,12 @@
android:endColor="#FFFFFF" />
</shape>
</item>
<item
android:width="220dp"
android:height="260dp"
android:gravity="center">
<bitmap
android:gravity="fill"
android:src="@drawable/splash_content" />
</item>
</layer-list>

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="LaunchTheme" parent="@android:style/Theme.Material.Light.NoActionBar">
<item name="android:windowBackground">@drawable/launch_background</item>
<item name="android:windowSplashScreenBackground">#F8FBFF</item>
<item name="android:windowSplashScreenAnimatedIcon">@drawable/splash_android12_icon</item>
<item name="android:windowSplashScreenIconBackgroundColor">#F8FBFF</item>
</style>
<style name="NormalTheme" parent="@android:style/Theme.Material.Light.NoActionBar">
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
</resources>

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
<style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
the Flutter engine draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
@@ -12,7 +12,7 @@
running.
This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
</resources>

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="LaunchTheme" parent="@android:style/Theme.Material.Light.NoActionBar">
<item name="android:windowBackground">@drawable/launch_background</item>
<item name="android:windowSplashScreenBackground">#F8FBFF</item>
<item name="android:windowSplashScreenAnimatedIcon">@drawable/splash_android12_icon</item>
<item name="android:windowSplashScreenIconBackgroundColor">#F8FBFF</item>
</style>
<style name="NormalTheme" parent="@android:style/Theme.Material.Light.NoActionBar">
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
</resources>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 B

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 B

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 B

After

Width:  |  Height:  |  Size: 72 KiB

View File

@@ -32,6 +32,6 @@
</scene>
</scenes>
<resources>
<image name="LaunchImage" width="168" height="185"/>
<image name="LaunchImage" width="220" height="260"/>
</resources>
</document>

View File

@@ -99,6 +99,7 @@ class _H5ShellPageState extends State<H5ShellPage> {
String? _loadError;
bool _showShellCover = true;
bool _shellBrandingLoaded = false;
Timer? _shellCoverFallbackTimer;
late ShellBranding _shellBranding;
@override
@@ -112,6 +113,10 @@ class _H5ShellPageState extends State<H5ShellPage> {
WebViewController _buildController() {
return WebViewController()
..setJavaScriptMode(JavaScriptMode.unrestricted)
..addJavaScriptChannel(
'OpenIMShell',
onMessageReceived: _handleShellMessage,
)
..setBackgroundColor(_shellBackground)
..setNavigationDelegate(
NavigationDelegate(
@@ -121,6 +126,7 @@ class _H5ShellPageState extends State<H5ShellPage> {
}
},
onPageStarted: (_) {
_shellCoverFallbackTimer?.cancel();
if (mounted) {
setState(() {
_loadError = null;
@@ -134,6 +140,7 @@ class _H5ShellPageState extends State<H5ShellPage> {
},
onWebResourceError: (error) {
if (error.isForMainFrame ?? true) {
_shellCoverFallbackTimer?.cancel();
if (mounted) {
setState(() {
_loadError = error.description;
@@ -147,6 +154,12 @@ class _H5ShellPageState extends State<H5ShellPage> {
);
}
@override
void dispose() {
_shellCoverFallbackTimer?.cancel();
super.dispose();
}
Future<void> _runJavaScriptSafely(String source) async {
try {
await _controller.runJavaScript(source);
@@ -165,9 +178,42 @@ class _H5ShellPageState extends State<H5ShellPage> {
if (mounted) {
setState(() {
_progress = 100;
_showShellCover = false;
});
}
_scheduleShellCoverFallback();
}
void _handleShellMessage(JavaScriptMessage message) {
try {
final decoded = jsonDecode(message.message);
if (decoded is Map && decoded['type'] == 'first-screen-ready') {
_hideShellCover();
}
} catch (_) {
if (message.message == 'first-screen-ready') {
_hideShellCover();
}
}
}
void _scheduleShellCoverFallback() {
_shellCoverFallbackTimer?.cancel();
_shellCoverFallbackTimer = Timer(
const Duration(seconds: 4),
_hideShellCover,
);
}
void _hideShellCover() {
_shellCoverFallbackTimer?.cancel();
if (!mounted || !_showShellCover) {
return;
}
setState(() {
_progress = 100;
_showShellCover = false;
});
}
Future<void> _loadShellBrandingIfNeeded() async {
@@ -212,6 +258,7 @@ class _H5ShellPageState extends State<H5ShellPage> {
final targetUrl = AppConfig.canonicalizeMainFrameUrl(url);
if (mounted) {
_shellCoverFallbackTimer?.cancel();
setState(() {
_loadError = null;
_progress = 0;