Skip to content

Commit 490f5cf

Browse files
committed
update: [MiuixPopupUtil] Optimize animations of dialogs and popups.
add: [MiuixPopupUtil] Animation for center-aligned dialogs
1 parent 6bcce1a commit 490f5cf

File tree

3 files changed

+104
-21
lines changed

3 files changed

+104
-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: 49 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,29 @@
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
5+
import androidx.compose.animation.core.spring
56
import androidx.compose.animation.core.tween
6-
import androidx.compose.animation.expandIn
77
import androidx.compose.animation.fadeIn
88
import androidx.compose.animation.fadeOut
99
import androidx.compose.animation.scaleIn
1010
import androidx.compose.animation.scaleOut
11-
import androidx.compose.animation.shrinkOut
1211
import androidx.compose.animation.slideInVertically
1312
import androidx.compose.animation.slideOutVertically
1413
import androidx.compose.foundation.background
1514
import androidx.compose.foundation.layout.fillMaxSize
1615
import androidx.compose.runtime.Composable
1716
import androidx.compose.runtime.MutableState
17+
import androidx.compose.runtime.derivedStateOf
18+
import androidx.compose.runtime.getValue
1819
import androidx.compose.runtime.mutableStateOf
20+
import androidx.compose.runtime.rememberUpdatedState
1921
import androidx.compose.ui.Modifier
22+
import androidx.compose.ui.platform.LocalDensity
23+
import androidx.compose.ui.unit.dp
2024
import androidx.compose.ui.zIndex
25+
import top.yukonga.miuix.kmp.anim.AccelerateEasing
26+
import top.yukonga.miuix.kmp.anim.DecelerateEasing
2127
import top.yukonga.miuix.kmp.basic.Box
2228
import top.yukonga.miuix.kmp.basic.Scaffold
2329
import top.yukonga.miuix.kmp.theme.MiuixTheme
@@ -90,11 +96,16 @@ class MiuixPopupUtil {
9096
*/
9197
@Composable
9298
fun MiuixPopupHost() {
99+
val density = LocalDensity.current
100+
val getWindowSize by rememberUpdatedState(getWindowSize())
101+
val windowWidth by rememberUpdatedState(getWindowSize.width.dp / density.density)
102+
val windowHeight by rememberUpdatedState(getWindowSize.height.dp / density.density)
103+
val largeScreen by rememberUpdatedState { derivedStateOf { (windowHeight >= 480.dp && windowWidth >= 840.dp) } }
93104
AnimatedVisibility(
94105
visible = isDialogShowing.value || isPopupShowing.value,
95106
modifier = Modifier.zIndex(1f).fillMaxSize(),
96-
enter = fadeIn(animationSpec = tween(500)),
97-
exit = fadeOut(animationSpec = tween(500))
107+
enter = fadeIn(animationSpec = tween(300, easing = DecelerateEasing(1.5f))),
108+
exit = fadeOut(animationSpec = tween(250, easing = DecelerateEasing(1.5f)))
98109
) {
99110
Box(
100111
modifier = Modifier
@@ -105,20 +116,35 @@ class MiuixPopupUtil {
105116
AnimatedVisibility(
106117
visible = isDialogShowing.value,
107118
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)
119+
enter = if (largeScreen.invoke().value) {
120+
fadeIn(
121+
animationSpec = spring(0.8f, Spring.StiffnessMediumLow),
122+
) + scaleIn(
123+
initialScale = 0.8f,
124+
animationSpec = spring(0.8f, Spring.StiffnessMediumLow),
113125
)
114-
),
115-
exit = slideOutVertically(
116-
targetOffsetY = { fullHeight -> fullHeight },
117-
animationSpec = tween(
118-
durationMillis = 300,
119-
easing = CubicBezierEasing(1f, 0f, 0.64f, 0f)
126+
} else {
127+
slideInVertically(
128+
initialOffsetY = { fullHeight -> fullHeight },
129+
animationSpec = spring(0.88f, Spring.StiffnessMediumLow)
120130
)
121-
)
131+
},
132+
exit = if (largeScreen.invoke().value) {
133+
fadeOut(
134+
animationSpec = tween(200, easing = DecelerateEasing(1.5f)
135+
)
136+
) + scaleOut(
137+
targetScale = 0.8f,
138+
animationSpec = tween(200, easing = DecelerateEasing(1.5f)
139+
)
140+
)
141+
} else {
142+
slideOutVertically(
143+
targetOffsetY = { fullHeight -> fullHeight },
144+
animationSpec = tween(200, easing = DecelerateEasing(1.5f)
145+
)
146+
)
147+
}
122148
) {
123149
Box(
124150
modifier = Modifier.fillMaxSize()
@@ -140,14 +166,16 @@ class MiuixPopupUtil {
140166
visible = isPopupShowing.value,
141167
modifier = Modifier.zIndex(2f).fillMaxSize(),
142168
enter = fadeIn(
143-
animationSpec = tween(150)
169+
animationSpec = tween(150, easing = DecelerateEasing(1.5f))
144170
) + scaleIn(
145-
animationSpec = tween(150), initialScale = 0.9f
171+
initialScale = 0.8f,
172+
animationSpec = tween(150, easing = DecelerateEasing(1.5f))
146173
),
147174
exit = fadeOut(
148-
animationSpec = tween(150)
175+
animationSpec = tween(150, easing = AccelerateEasing(3.0f))
149176
) + scaleOut(
150-
animationSpec = tween(150), targetScale = 0.9f
177+
targetScale = 0.8f,
178+
animationSpec = tween(150, easing = AccelerateEasing(3.0f))
151179
)
152180
) {
153181
Box(

0 commit comments

Comments
 (0)