feat: 添加启动屏幕图像和主题样式;优化 H5 壳的封面隐藏逻辑
|
After Width: | Height: | Size: 39 KiB |
BIN
android/app/src/main/res/drawable-nodpi/splash_content.png
Normal file
|
After Width: | Height: | Size: 72 KiB |
@@ -9,4 +9,12 @@
|
|||||||
android:endColor="#FFFFFF" />
|
android:endColor="#FFFFFF" />
|
||||||
</shape>
|
</shape>
|
||||||
</item>
|
</item>
|
||||||
|
<item
|
||||||
|
android:width="220dp"
|
||||||
|
android:height="260dp"
|
||||||
|
android:gravity="center">
|
||||||
|
<bitmap
|
||||||
|
android:gravity="fill"
|
||||||
|
android:src="@drawable/splash_content" />
|
||||||
|
</item>
|
||||||
</layer-list>
|
</layer-list>
|
||||||
|
|||||||
@@ -9,4 +9,12 @@
|
|||||||
android:endColor="#FFFFFF" />
|
android:endColor="#FFFFFF" />
|
||||||
</shape>
|
</shape>
|
||||||
</item>
|
</item>
|
||||||
|
<item
|
||||||
|
android:width="220dp"
|
||||||
|
android:height="260dp"
|
||||||
|
android:gravity="center">
|
||||||
|
<bitmap
|
||||||
|
android:gravity="fill"
|
||||||
|
android:src="@drawable/splash_content" />
|
||||||
|
</item>
|
||||||
</layer-list>
|
</layer-list>
|
||||||
|
|||||||
13
android/app/src/main/res/values-night-v31/styles.xml
Normal 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>
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
|
<!-- 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
|
<!-- Show a splash screen on the activity. Automatically removed when
|
||||||
the Flutter engine draws its first frame -->
|
the Flutter engine draws its first frame -->
|
||||||
<item name="android:windowBackground">@drawable/launch_background</item>
|
<item name="android:windowBackground">@drawable/launch_background</item>
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
running.
|
running.
|
||||||
|
|
||||||
This Theme is only used starting with V2 of Flutter's Android embedding. -->
|
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>
|
<item name="android:windowBackground">@drawable/launch_background</item>
|
||||||
</style>
|
</style>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
13
android/app/src/main/res/values-v31/styles.xml
Normal 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>
|
||||||
|
Before Width: | Height: | Size: 68 B After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 68 B After Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 68 B After Width: | Height: | Size: 72 KiB |
@@ -32,6 +32,6 @@
|
|||||||
</scene>
|
</scene>
|
||||||
</scenes>
|
</scenes>
|
||||||
<resources>
|
<resources>
|
||||||
<image name="LaunchImage" width="168" height="185"/>
|
<image name="LaunchImage" width="220" height="260"/>
|
||||||
</resources>
|
</resources>
|
||||||
</document>
|
</document>
|
||||||
|
|||||||
@@ -99,6 +99,7 @@ class _H5ShellPageState extends State<H5ShellPage> {
|
|||||||
String? _loadError;
|
String? _loadError;
|
||||||
bool _showShellCover = true;
|
bool _showShellCover = true;
|
||||||
bool _shellBrandingLoaded = false;
|
bool _shellBrandingLoaded = false;
|
||||||
|
Timer? _shellCoverFallbackTimer;
|
||||||
late ShellBranding _shellBranding;
|
late ShellBranding _shellBranding;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -112,6 +113,10 @@ class _H5ShellPageState extends State<H5ShellPage> {
|
|||||||
WebViewController _buildController() {
|
WebViewController _buildController() {
|
||||||
return WebViewController()
|
return WebViewController()
|
||||||
..setJavaScriptMode(JavaScriptMode.unrestricted)
|
..setJavaScriptMode(JavaScriptMode.unrestricted)
|
||||||
|
..addJavaScriptChannel(
|
||||||
|
'OpenIMShell',
|
||||||
|
onMessageReceived: _handleShellMessage,
|
||||||
|
)
|
||||||
..setBackgroundColor(_shellBackground)
|
..setBackgroundColor(_shellBackground)
|
||||||
..setNavigationDelegate(
|
..setNavigationDelegate(
|
||||||
NavigationDelegate(
|
NavigationDelegate(
|
||||||
@@ -121,6 +126,7 @@ class _H5ShellPageState extends State<H5ShellPage> {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
onPageStarted: (_) {
|
onPageStarted: (_) {
|
||||||
|
_shellCoverFallbackTimer?.cancel();
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
setState(() {
|
setState(() {
|
||||||
_loadError = null;
|
_loadError = null;
|
||||||
@@ -134,6 +140,7 @@ class _H5ShellPageState extends State<H5ShellPage> {
|
|||||||
},
|
},
|
||||||
onWebResourceError: (error) {
|
onWebResourceError: (error) {
|
||||||
if (error.isForMainFrame ?? true) {
|
if (error.isForMainFrame ?? true) {
|
||||||
|
_shellCoverFallbackTimer?.cancel();
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
setState(() {
|
setState(() {
|
||||||
_loadError = error.description;
|
_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 {
|
Future<void> _runJavaScriptSafely(String source) async {
|
||||||
try {
|
try {
|
||||||
await _controller.runJavaScript(source);
|
await _controller.runJavaScript(source);
|
||||||
@@ -165,9 +178,42 @@ class _H5ShellPageState extends State<H5ShellPage> {
|
|||||||
if (mounted) {
|
if (mounted) {
|
||||||
setState(() {
|
setState(() {
|
||||||
_progress = 100;
|
_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 {
|
Future<void> _loadShellBrandingIfNeeded() async {
|
||||||
@@ -212,6 +258,7 @@ class _H5ShellPageState extends State<H5ShellPage> {
|
|||||||
final targetUrl = AppConfig.canonicalizeMainFrameUrl(url);
|
final targetUrl = AppConfig.canonicalizeMainFrameUrl(url);
|
||||||
|
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
|
_shellCoverFallbackTimer?.cancel();
|
||||||
setState(() {
|
setState(() {
|
||||||
_loadError = null;
|
_loadError = null;
|
||||||
_progress = 0;
|
_progress = 0;
|
||||||
|
|||||||