Skip to content

Commit 52130a6

Browse files
authored
library: Optimize Popup Animation (#26)
1 parent 6bcce1a commit 52130a6

File tree

3 files changed

+100
-21
lines changed

3 files changed

+100
-21
lines changed
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package top.yukonga.miuix.kmp.anim
2+
3+
import androidx.compose.animation.core.Easing
4+
import androidx.compose.runtime.Immutable
5+
import kotlin.math.pow
6+
7+
/**
8+
* This is equivalent to the Android [AccelerateInterpolator](https://cs.android.com/search?q=file:androidx/core/animation/AccelerateInterpolator.java+class:androidx.core.animation.AccelerateInterpolator)
9+
*
10+
* @param factor Degree to which the animation should be eased. Setting
11+
* factor to 1.0f produces a y=x^2 parabola. Increasing factor above
12+
* 1.0f exaggerates the ease-in effect (i.e., it starts even
13+
* slower and ends evens faster)
14+
*/
15+
@Immutable
16+
class AccelerateEasing(
17+
private val factor: Float = 1.0f
18+
) : Easing {
19+
private val doubleFactor: Float = 2 * factor
20+
21+
override fun transform(fraction: Float): Float {
22+
return if (factor == 1.0f) {
23+
fraction * fraction
24+
} else {
25+
fraction.pow(doubleFactor)
26+
}
27+
}
28+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
2+
3+
package top.yukonga.miuix.kmp.anim
4+
5+
import androidx.compose.animation.core.Easing
6+
import androidx.compose.runtime.Immutable
7+
import kotlin.math.pow
8+
9+
/**
10+
* This is equivalent to the Android [DecelerateInterpolator](https://cs.android.com/search?q=file:androidx/core/animation/DecelerateInterpolator.java+class:androidx.core.animation.DecelerateInterpolator)
11+
*
12+
* @param factor Degree to which the animation should be eased. Setting factor to 1.0f produces
13+
* an upside-down y=x^2 parabola. Increasing factor above 1.0f makes exaggerates the
14+
* ease-out effect (i.e., it starts even faster and ends evens slower)
15+
*/
16+
@Immutable
17+
class DecelerateEasing(
18+
private val factor: Float = 1.0f
19+
) : Easing {
20+
override fun transform(fraction: Float): Float {
21+
return if (factor == 1.0f) {
22+
1.0f - (1.0f - fraction) * (1.0f - fraction)
23+
} else {
24+
1.0f - (1.0f - fraction).pow(2 * fraction)
25+
}
26+
}
27+
}

miuix/src/commonMain/kotlin/top/yukonga/miuix/kmp/utils/MiuixPopupUtil.kt

Lines changed: 45 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,28 @@
11
package top.yukonga.miuix.kmp.utils
22

33
import androidx.compose.animation.AnimatedVisibility
4-
import androidx.compose.animation.core.CubicBezierEasing
4+
import androidx.compose.animation.core.spring
55
import androidx.compose.animation.core.tween
6-
import androidx.compose.animation.expandIn
76
import androidx.compose.animation.fadeIn
87
import androidx.compose.animation.fadeOut
98
import androidx.compose.animation.scaleIn
109
import androidx.compose.animation.scaleOut
11-
import androidx.compose.animation.shrinkOut
1210
import androidx.compose.animation.slideInVertically
1311
import androidx.compose.animation.slideOutVertically
1412
import androidx.compose.foundation.background
1513
import androidx.compose.foundation.layout.fillMaxSize
1614
import androidx.compose.runtime.Composable
1715
import androidx.compose.runtime.MutableState
16+
import androidx.compose.runtime.derivedStateOf
17+
import androidx.compose.runtime.getValue
1818
import androidx.compose.runtime.mutableStateOf
19+
import androidx.compose.runtime.rememberUpdatedState
1920
import androidx.compose.ui.Modifier
21+
import androidx.compose.ui.platform.LocalDensity
22+
import androidx.compose.ui.unit.dp
2023
import androidx.compose.ui.zIndex
24+
import top.yukonga.miuix.kmp.anim.AccelerateEasing
25+
import top.yukonga.miuix.kmp.anim.DecelerateEasing
2126
import top.yukonga.miuix.kmp.basic.Box
2227
import top.yukonga.miuix.kmp.basic.Scaffold
2328
import top.yukonga.miuix.kmp.theme.MiuixTheme
@@ -90,11 +95,16 @@ class MiuixPopupUtil {
9095
*/
9196
@Composable
9297
fun MiuixPopupHost() {
98+
val density = LocalDensity.current
99+
val getWindowSize by rememberUpdatedState(getWindowSize())
100+
val windowWidth by rememberUpdatedState(getWindowSize.width.dp / density.density)
101+
val windowHeight by rememberUpdatedState(getWindowSize.height.dp / density.density)
102+
val largeScreen by rememberUpdatedState { derivedStateOf { (windowHeight >= 480.dp && windowWidth >= 840.dp) } }
93103
AnimatedVisibility(
94104
visible = isDialogShowing.value || isPopupShowing.value,
95105
modifier = Modifier.zIndex(1f).fillMaxSize(),
96-
enter = fadeIn(animationSpec = tween(500)),
97-
exit = fadeOut(animationSpec = tween(500))
106+
enter = fadeIn(animationSpec = tween(300, easing = DecelerateEasing(1.5f))),
107+
exit = fadeOut(animationSpec = tween(250, easing = DecelerateEasing(1.5f)))
98108
) {
99109
Box(
100110
modifier = Modifier
@@ -105,20 +115,32 @@ class MiuixPopupUtil {
105115
AnimatedVisibility(
106116
visible = isDialogShowing.value,
107117
modifier = Modifier.zIndex(2f).fillMaxSize(),
108-
enter = slideInVertically(
109-
initialOffsetY = { fullHeight -> fullHeight },
110-
animationSpec = tween(
111-
durationMillis = 500,
112-
easing = CubicBezierEasing(0f, 1f, 0.36f, 1f)
118+
enter = if (largeScreen.invoke().value) {
119+
fadeIn(
120+
animationSpec = spring(0.9f, 900f)
121+
) + scaleIn(
122+
initialScale = 0.8f,
123+
animationSpec = spring(0.73f, 900f)
113124
)
114-
),
115-
exit = slideOutVertically(
116-
targetOffsetY = { fullHeight -> fullHeight },
117-
animationSpec = tween(
118-
durationMillis = 300,
119-
easing = CubicBezierEasing(1f, 0f, 0.64f, 0f)
125+
} else {
126+
slideInVertically(
127+
initialOffsetY = { fullHeight -> fullHeight },
128+
animationSpec = spring(0.92f, 500f)
120129
)
121-
)
130+
},
131+
exit = if (largeScreen.invoke().value) {
132+
fadeOut(
133+
animationSpec = tween(200, easing = DecelerateEasing(1.5f))
134+
) + scaleOut(
135+
targetScale = 0.8f,
136+
animationSpec = tween(200, easing = DecelerateEasing(1.5f))
137+
)
138+
} else {
139+
slideOutVertically(
140+
targetOffsetY = { fullHeight -> fullHeight },
141+
animationSpec = tween(200, easing = DecelerateEasing(1.5f))
142+
)
143+
}
122144
) {
123145
Box(
124146
modifier = Modifier.fillMaxSize()
@@ -140,14 +162,16 @@ class MiuixPopupUtil {
140162
visible = isPopupShowing.value,
141163
modifier = Modifier.zIndex(2f).fillMaxSize(),
142164
enter = fadeIn(
143-
animationSpec = tween(150)
165+
animationSpec = tween(150, easing = DecelerateEasing(1.5f))
144166
) + scaleIn(
145-
animationSpec = tween(150), initialScale = 0.9f
167+
initialScale = 0.8f,
168+
animationSpec = tween(150, easing = DecelerateEasing(1.5f))
146169
),
147170
exit = fadeOut(
148-
animationSpec = tween(150)
171+
animationSpec = tween(150, easing = AccelerateEasing(3.0f))
149172
) + scaleOut(
150-
animationSpec = tween(150), targetScale = 0.9f
173+
targetScale = 0.8f,
174+
animationSpec = tween(150, easing = AccelerateEasing(3.0f))
151175
)
152176
) {
153177
Box(

0 commit comments

Comments
 (0)