diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 7df196f..32abcd2 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -10,15 +10,19 @@
android:supportsRtl="true"
android:theme="@style/Theme.YaYa">
+ android:theme="@style/Theme.YaYa.Splash">
+
+
diff --git a/app/src/main/kotlin/plus/rua/project/MainActivity.kt b/app/src/main/kotlin/plus/rua/project/MainActivity.kt
index 6ea86af..f9a24a4 100644
--- a/app/src/main/kotlin/plus/rua/project/MainActivity.kt
+++ b/app/src/main/kotlin/plus/rua/project/MainActivity.kt
@@ -4,13 +4,11 @@ import android.content.Intent
import android.os.Bundle
import androidx.activity.compose.ReportDrawn
import androidx.activity.compose.setContent
-import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
import plus.rua.project.ui.CalendarMonthView
import plus.rua.project.ui.theme.YaYaTheme
class MainActivity : BaseActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
- installSplashScreen()
super.onCreate(savedInstanceState)
setContent {
diff --git a/app/src/main/kotlin/plus/rua/project/SplashActivity.kt b/app/src/main/kotlin/plus/rua/project/SplashActivity.kt
new file mode 100644
index 0000000..0042805
--- /dev/null
+++ b/app/src/main/kotlin/plus/rua/project/SplashActivity.kt
@@ -0,0 +1,43 @@
+package plus.rua.project
+
+import android.content.Intent
+import android.os.Bundle
+import androidx.activity.compose.setContent
+import androidx.compose.ui.res.painterResource
+import androidx.lifecycle.lifecycleScope
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.launch
+import plus.rua.project.ui.SplashScreen
+import plus.rua.project.ui.theme.YaYaTheme
+
+private const val SPLASH_DELAY_MS = 400L
+
+/**
+ * 启动页 Activity。
+ *
+ * 显示品牌启动图 400ms 后跳转到 [MainActivity],并 finish 自身。
+ */
+class SplashActivity : BaseActivity() {
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ setContent {
+ YaYaTheme {
+ SplashScreen(
+ iconPainter = painterResource(R.mipmap.ic_launcher),
+ )
+ }
+ }
+
+ lifecycleScope.launch {
+ delay(SPLASH_DELAY_MS)
+ navigateToMain()
+ }
+ }
+
+ private fun navigateToMain() {
+ if (isFinishing) return
+ startActivityWithSlide(Intent(this, MainActivity::class.java))
+ finish()
+ }
+}
diff --git a/app/src/main/res/values-night/themes.xml b/app/src/main/res/values-night/themes.xml
index 6138c74..58abbfb 100644
--- a/app/src/main/res/values-night/themes.xml
+++ b/app/src/main/res/values-night/themes.xml
@@ -2,8 +2,15 @@
+
+
+
diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml
index e498332..2297d58 100644
--- a/app/src/main/res/values/themes.xml
+++ b/app/src/main/res/values/themes.xml
@@ -5,10 +5,15 @@
+
+
diff --git a/core/src/main/kotlin/plus/rua/project/ui/SplashScreen.kt b/core/src/main/kotlin/plus/rua/project/ui/SplashScreen.kt
new file mode 100644
index 0000000..89932c7
--- /dev/null
+++ b/core/src/main/kotlin/plus/rua/project/ui/SplashScreen.kt
@@ -0,0 +1,64 @@
+package plus.rua.project.ui
+
+import androidx.compose.foundation.Image
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.WindowInsets
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.layout.statusBars
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.painter.Painter
+import androidx.compose.ui.layout.ContentScale
+import androidx.compose.ui.platform.LocalConfiguration
+import androidx.compose.ui.platform.LocalDensity
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.unit.dp
+import plus.rua.project.shared.R as CoreR
+
+private val SplashIconSize = 80.dp
+
+/**
+ * 品牌启动页 UI。
+ *
+ * 背景图铺满全屏,Light/Dark 资源由 Android 根据配置自动选择。
+ * app icon 水平居中,其垂直中心位于状态栏下方可用区域高度的约 25% 处。
+ * 图片仅用于装饰,因此 contentDescription 为 null。
+ *
+ * @param iconPainter app icon 的 Painter
+ * @param modifier 外部传入的 Modifier
+ */
+@Composable
+fun SplashScreen(
+ iconPainter: Painter,
+ modifier: Modifier = Modifier,
+) {
+ val configuration = LocalConfiguration.current
+ val density = LocalDensity.current
+ val screenHeightDp = configuration.screenHeightDp.dp
+ val statusBarHeight = with(density) { WindowInsets.statusBars.getTop(this).toDp() }
+ val availableHeight = screenHeightDp - statusBarHeight
+ val iconTopPadding = statusBarHeight + (availableHeight * 0.25f) - (SplashIconSize / 2)
+
+ Box(
+ modifier = modifier.fillMaxSize(),
+ ) {
+ Image(
+ painter = painterResource(CoreR.drawable.launch_bg),
+ contentDescription = null,
+ contentScale = ContentScale.Crop,
+ modifier = Modifier.fillMaxSize(),
+ )
+
+ Image(
+ painter = iconPainter,
+ contentDescription = null,
+ modifier = Modifier
+ .align(Alignment.TopCenter)
+ .padding(top = iconTopPadding.coerceAtLeast(statusBarHeight))
+ .size(SplashIconSize),
+ )
+ }
+}