|
4 | 4 | package top.yukonga.miuix.kmp.basic |
5 | 5 |
|
6 | 6 | import androidx.compose.animation.AnimatedVisibility |
| 7 | +import androidx.compose.animation.core.FiniteAnimationSpec |
7 | 8 | import androidx.compose.animation.core.MutableTransitionState |
| 9 | +import androidx.compose.animation.core.Spring |
| 10 | +import androidx.compose.animation.core.spring |
8 | 11 | import androidx.compose.animation.fadeIn |
9 | 12 | import androidx.compose.animation.fadeOut |
10 | 13 | import androidx.compose.animation.scaleIn |
@@ -169,7 +172,11 @@ private class TooltipStateImpl( |
169 | 172 | MutableTransitionState(initialIsVisible) |
170 | 173 |
|
171 | 174 | override val isVisible: Boolean |
172 | | - get() = transition.currentState || transition.targetState |
| 175 | + // Keep the popup composed while shown or still animating. Gating on currentState would |
| 176 | + // hard-cut the exit when a dismiss interrupts an unfinished enter, since currentState only |
| 177 | + // flips to true once the enter has settled; !isIdle keeps it through the reversal so the |
| 178 | + // exit can animate out. |
| 179 | + get() = transition.targetState || !transition.isIdle |
173 | 180 |
|
174 | 181 | /** continuation used to clean up */ |
175 | 182 | private var job: (CancellableContinuation<Unit>)? = null |
@@ -237,6 +244,14 @@ fun rememberTooltipState( |
237 | 244 | TooltipStateImpl(initialIsVisible, isPersistent, mutatorMutex) |
238 | 245 | } |
239 | 246 |
|
| 247 | +/** |
| 248 | + * Spring driving the tooltip's exit scale. A spring (not a tween) honors the inbound velocity left |
| 249 | + * by the enter spring when a dismiss interrupts an unsettled enter, so the reversal stays smooth; a |
| 250 | + * tween would discard that velocity and produce a stall-and-reverse hitch. |
| 251 | + */ |
| 252 | +private val TooltipExitScaleSpec: FiniteAnimationSpec<Float> = |
| 253 | + spring(dampingRatio = Spring.DampingRatioNoBouncy, stiffness = Spring.StiffnessMedium, visibilityThreshold = 0.0001f) |
| 254 | + |
240 | 255 | /** |
241 | 256 | * A tooltip box that anchors a [tooltip] (a [PlainTooltip] or [RichTooltip]) to its [content]. |
242 | 257 | * |
@@ -276,7 +291,7 @@ fun TooltipBox( |
276 | 291 | enter = fadeIn(ListPopupDefaults.AlphaEnterAnimationSpec) + |
277 | 292 | scaleIn(initialScale = 0.9f, animationSpec = ListPopupDefaults.FractionAnimationSpec), |
278 | 293 | exit = fadeOut(ListPopupDefaults.AlphaExitAnimationSpec) + |
279 | | - scaleOut(targetScale = 0.9f, animationSpec = ListPopupDefaults.AlphaExitAnimationSpec), |
| 294 | + scaleOut(targetScale = 0.9f, animationSpec = TooltipExitScaleSpec), |
280 | 295 | ) { |
281 | 296 | scope.tooltip() |
282 | 297 | } |
|
0 commit comments