Skip to content

Commit

Permalink
✨ [kmp/android] 完成了对启动屏动画的改造
Browse files Browse the repository at this point in the history
  • Loading branch information
Gaubee committed Jun 22, 2024
1 parent 505db87 commit 88a37d9
Show file tree
Hide file tree
Showing 12 changed files with 344 additions and 164 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,22 @@ import android.os.Bundle
import androidx.activity.compose.setContent
import androidx.appcompat.app.AppCompatActivity
import androidx.compose.animation.animateColorAsState
import androidx.compose.animation.core.EaseInOutQuart
import androidx.compose.animation.core.FastOutSlowInEasing
import androidx.compose.animation.core.animateDpAsState
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.core.tween
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.BoxWithConstraints
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.requiredSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.mutableStateOf
Expand All @@ -28,13 +31,14 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.min
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
import androidx.core.view.WindowCompat
import kotlinx.atomicfu.atomic
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.delay
Expand All @@ -43,6 +47,7 @@ import org.dweb_browser.browser.common.CommonWebView
import org.dweb_browser.browser.common.SplashPrivacyDialog
import org.dweb_browser.core.module.NativeMicroModule
import org.dweb_browser.core.module.interceptStartApp
import org.dweb_browser.helper.Once1
import org.dweb_browser.helper.compose.LocalCommonUrl
import org.dweb_browser.helper.getBoolean
import org.dweb_browser.helper.globalMainScope
Expand All @@ -52,18 +57,12 @@ import kotlin.system.exitProcess

@SuppressLint("CustomSplashScreen")
class SplashActivity : AppCompatActivity() {
private var mKeepOnAtomicBool by atomic(true)
private var mKeepOnAtomicBool by mutableStateOf(true)
private val keyEnableAgreement = "enable.agreement" // 判断是否第一次运行程序

@OptIn(ExperimentalCoroutinesApi::class)
@SuppressLint("ObjectAnimatorBinding", "CoroutineCreationDuringComposition")
override fun onCreate(savedInstanceState: Bundle?) {
// enableEdgeToEdge() // 全屏
WindowCompat.setDecorFitsSystemWindows(window, false) // 全屏

super.onCreate(savedInstanceState)

val agree = this.getBoolean(keyEnableAgreement, false) // 获取隐私协议状态
@OptIn(ExperimentalCoroutinesApi::class)
private val grantInstaller = Once1 { agree: Boolean ->
// 启动屏幕的安装 必须放在setContent之前
val splashScreen = installSplashScreen().also {
it.setKeepOnScreenCondition { mKeepOnAtomicBool } // 使用mKeepOnAtomicBool状态控制欢迎界面
Expand Down Expand Up @@ -92,11 +91,24 @@ class SplashActivity : AppCompatActivity() {
/// 启动应用
DwebBrowserApp.startMicroModuleProcess() // 启动MicroModule

grant
}

@OptIn(ExperimentalCoroutinesApi::class)
@SuppressLint("ObjectAnimatorBinding", "CoroutineCreationDuringComposition")
override fun onCreate(savedInstanceState: Bundle?) {
// enableEdgeToEdge() // 全屏
WindowCompat.setDecorFitsSystemWindows(window, false) // 全屏

super.onCreate(savedInstanceState)
val agree = this.getBoolean(keyEnableAgreement, false) // 获取隐私协议状态
val grant = grantInstaller(agree)

setContent {
var localPrivacy by LocalCommonUrl.current

DwebBrowserAppTheme {
SplashMainView()
SplashMainView(startAnimation = !mKeepOnAtomicBool)
if (agree) {
return@DwebBrowserAppTheme
}
Expand Down Expand Up @@ -125,59 +137,80 @@ class SplashActivity : AppCompatActivity() {
}

@Composable
fun SplashMainView() {
fun dpAni(targetValue: Dp, label: String, onFinished: () -> Unit = {}): Dp {
return animateDpAsState(targetValue,
animationSpec = tween(800, easing = EaseInOutQuart),
label = label,
finishedListener = { onFinished() }).value
}

@Composable
fun SplashMainView(startAnimation: Boolean) {
BoxWithConstraints(
Modifier.fillMaxSize().background(MaterialTheme.colorScheme.background),
contentAlignment = Alignment.TopCenter,
contentAlignment = Alignment.Center,
) {
val size = min(maxWidth, maxHeight)
Column(
modifier = Modifier.size(size * 1.618f), horizontalAlignment = Alignment.CenterHorizontally
) {
Box(Modifier.weight(0.382f))
BoxWithConstraints(
Modifier.fillMaxSize().weight(1f), contentAlignment = Alignment.Center
) {
Image(
imageVector = ImageVector.vectorResource(R.drawable.ic_launcher_foreground),
contentDescription = "Dweb Browser Logo",
modifier = Modifier.size(min(maxWidth, maxHeight))
)
var aniStart by remember { mutableStateOf(false) }
val logoHeight = 288.dp//maxHeight * 0.566f
var logoTop by remember { mutableStateOf(0.dp) }
val bannerTop = logoHeight / 2 + logoTop

if (startAnimation) {
LaunchedEffect(null) {
delay(10)
val boxSize = min(maxWidth, maxHeight) * 1.618f
logoTop = (boxSize * 0.217f) - ((maxHeight - logoHeight) / 2)
delay(500)
aniStart = true
}
Box(Modifier.weight(0.382f), contentAlignment = Alignment.TopCenter) {
var brushStartX by remember { mutableFloatStateOf(0.5f) }
var brushEndX by remember { mutableFloatStateOf(0.5f) }
var brushColor by remember { mutableStateOf(Color.Transparent) }
val brushToColor = MaterialTheme.colorScheme.primary
val animationSpec = tween<Float>(durationMillis = 2000, easing = FastOutSlowInEasing)
val startX by animateFloatAsState(
brushStartX, label = "startX", animationSpec = animationSpec
)
val endX by animateFloatAsState(brushEndX, label = "endX", animationSpec = animationSpec)
val color by animateColorAsState(
brushColor,
label = "color",
animationSpec = tween(durationMillis = 2000, easing = FastOutSlowInEasing)
)
val brush = Brush.horizontalGradient(
colorStops = arrayOf(
0f to Color.Transparent,
startX to color,
0.5f to brushToColor,
endX to color,
1f to Color.Transparent,
),
)
Text(" Dweb Browser ", style = MaterialTheme.typography.headlineLarge.merge(
TextStyle(
brush = brush,
)
), modifier = Modifier.onGloballyPositioned {
brushStartX = 0f
brushEndX = 1f
brushColor = brushToColor
})
}

val logoOffsetY = dpAni(logoTop, "logoPaddingTop")
Image(imageVector = ImageVector.vectorResource(R.drawable.ic_launcher_foreground),
contentDescription = "Dweb Browser Logo",
modifier = Modifier.requiredSize(288.dp).offset {
IntOffset(0, (logoOffsetY.value * density).toInt())
})
val bannerOffsetY = dpAni(bannerTop, "bannerPaddingTop")
Box(
Modifier.offset {
IntOffset(0, (bannerOffsetY.value * density).toInt())
},
contentAlignment = Alignment.TopCenter,
) {
var brushStartX by remember { mutableFloatStateOf(0.5f) }
var brushEndX by remember { mutableFloatStateOf(0.5f) }
var brushColor by remember { mutableStateOf(Color.Transparent) }
val toColor = MaterialTheme.colorScheme.primary
if (aniStart) {
brushStartX = 0f
brushEndX = 1f
brushColor = toColor
}
val animationSpec =
remember { tween<Float>(durationMillis = 2000, easing = FastOutSlowInEasing) }
val startX by animateFloatAsState(
brushStartX, label = "startX", animationSpec = animationSpec
)
val endX by animateFloatAsState(brushEndX, label = "endX", animationSpec = animationSpec)
val color by animateColorAsState(
brushColor,
label = "color",
animationSpec = tween(durationMillis = 2000, easing = FastOutSlowInEasing)
)
val brush = Brush.horizontalGradient(
colorStops = arrayOf(
0f to Color.Transparent,
startX to color,
0.5f to toColor,
endX to color,
1f to Color.Transparent,
),
)
Text(
" Dweb Browser ",
style = MaterialTheme.typography.headlineLarge.merge(TextStyle(brush = brush)),
)
}
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="windowSplashScreenBackground">#000000</color>
</resources>
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<resources>
<style name="AppTheme" parent="Theme.AppCompat.DayNight.NoActionBar" />
</resources>

This file was deleted.

21 changes: 0 additions & 21 deletions next/kmp/app/androidApp/src/androidMain/res/values-v31/themes.xml

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="windowSplashScreenBackground">#FFFFFF</color>
<color name="purple_200">#FFBB86FC</color>
<color name="purple_500">#FF6200EE</color>
<color name="purple_700">#FF3700B3</color>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
<resources>

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar" />
</resources>
12 changes: 3 additions & 9 deletions next/kmp/app/androidApp/src/androidMain/res/values/themes.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,12 @@
<!-- Splash启动页Style -->
<style name="Theme.App.Starting" parent="Theme.SplashScreen">
<!--启动画面背景颜色-->
<item name="windowSplashScreenBackground">#FFFFFF</item>
<item name="windowSplashScreenBackground">@color/windowSplashScreenBackground</item>
<!-- 启动画面icon图标:这里可以是图片、帧动画等-->
<item name="windowSplashScreenAnimatedIcon">@drawable/ic_launcher_foreground</item>
<item name="windowSplashScreenIconBackgroundColor">#ff00ff</item>

<!-- icon动画在关闭之前显示的时长:最长时间为1000毫秒-->
<item name="windowSplashScreenAnimationDuration">200</item>

<!-- 启动画面底部的 Brand 图片-->
<!--<item name="android:windowSplashScreenBrandingImage">@drawable/ic_branding</item>-->
<!-- <item name="windowSplashScreenIconBackgroundColor">#ff00ff</item>-->

<!-- Splash退出后的主题-->
<item name="postSplashScreenTheme">@style/Theme.AppCompat.Light.NoActionBar</item>
<item name="postSplashScreenTheme">@style/AppTheme</item>
</style>
</resources>
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,8 @@ object BrowserI18nResource {

val privacy_title = SimpleI18nResource(Language.ZH to "温馨提示", Language.EN to "Tips")
val privacy_content = SimpleI18nResource(
Language.ZH to "欢迎使用 Dweb Browser,在您使用的时候,需要连接网络,产生的流量费用请咨询当地运营商。在使用 Dweb Browser 前,请认真阅读《隐私协议》。您需要同意并接受全部条款后再开始使用该软件。",
Language.EN to "Welcome to Dweb Browser. Please note that an internet connection is required for use. Please consult your local operator for any data charges that may apply. Before using Dweb Browser, please carefully read the 'Privacy Policy'. You must agree to and accept all terms and conditions before using the software."
Language.ZH to "欢迎使用 Dweb Browser,在您使用的时候,需要连接网络,产生的流量费用请咨询当地运营商。\n在使用 Dweb Browser 前,请认真阅读《隐私协议》。您需要同意并接受全部条款后再开始使用该软件。",
Language.EN to "Welcome to Dweb Browser. Please note that an internet connection is required for use. Please consult your local operator for any data charges that may apply.\nBefore using Dweb Browser, please carefully read the 'Privacy Policy'. You must agree to and accept all terms and conditions before using the software."
)
val privacy_policy =
SimpleI18nResource(Language.ZH to "《隐私协议》", Language.EN to "'Privacy Policy'")
Expand Down
Loading

0 comments on commit 88a37d9

Please sign in to comment.