Skip to content

Commit 292b0b3

Browse files
committed
library: SuperBottomSheet: Add animation effects to tooltips
1 parent d9908a8 commit 292b0b3

File tree

4 files changed

+133
-38
lines changed

4 files changed

+133
-38
lines changed

example/src/commonMain/kotlin/MainPage.kt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,9 @@ fun MainPage(
8585
var expanded by remember { mutableStateOf(false) }
8686
val showDialog = remember { mutableStateOf(false) }
8787
val dialogTextFieldValue = remember { mutableStateOf("") }
88-
val showDialog2 = remember { mutableStateOf(false) }
89-
val dialog2dropdownSelectedOption = remember { mutableStateOf(0) }
90-
val dialog2SuperSwitchState = remember { mutableStateOf(false) }
88+
val showBottomSheet = remember { mutableStateOf(false) }
89+
val bottomSheetDropdownSelectedOption = remember { mutableStateOf(0) }
90+
val bottomSheetSuperSwitchState = remember { mutableStateOf(true) }
9191
val checkbox = remember { mutableStateOf(false) }
9292
val checkboxTrue = remember { mutableStateOf(true) }
9393
val switch = remember { mutableStateOf(false) }
@@ -111,9 +111,9 @@ fun MainPage(
111111
TextComponent(
112112
showDialog,
113113
dialogTextFieldValue,
114-
showDialog2,
115-
dialog2dropdownSelectedOption,
116-
dialog2SuperSwitchState,
114+
showBottomSheet = showBottomSheet,
115+
bottomSheetDropdownSelectedOption,
116+
bottomSheetSuperSwitchState,
117117
checkbox,
118118
checkboxTrue,
119119
switch,

example/src/commonMain/kotlin/component/TextComponent.kt

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,10 @@ import androidx.compose.foundation.layout.Arrangement
1212
import androidx.compose.foundation.layout.Box
1313
import androidx.compose.foundation.layout.Row
1414
import androidx.compose.foundation.layout.Spacer
15+
import androidx.compose.foundation.layout.WindowInsets
16+
import androidx.compose.foundation.layout.asPaddingValues
1517
import androidx.compose.foundation.layout.fillMaxWidth
18+
import androidx.compose.foundation.layout.navigationBars
1619
import androidx.compose.foundation.layout.padding
1720
import androidx.compose.foundation.layout.width
1821
import androidx.compose.runtime.Composable
@@ -531,13 +534,21 @@ fun BottomSheet(
531534
}
532535
)
533536
}
534-
val miuixColor = MiuixTheme.colorScheme.primary
535-
var selectedColor by remember { mutableStateOf(miuixColor) }
536-
ColorPalette(
537-
initialColor = selectedColor,
538-
onColorChanged = { selectedColor = it },
539-
showPreview = false
540-
)
537+
AnimatedVisibility(
538+
visible = bottomSheetSuperSwitchState.value,
539+
enter = fadeIn() + expandVertically(),
540+
exit = fadeOut() + shrinkVertically()
541+
) {
542+
val miuixColor = MiuixTheme.colorScheme.primary
543+
var selectedColor by remember { mutableStateOf(miuixColor) }
544+
ColorPalette(
545+
modifier = Modifier.padding(bottom = 12.dp),
546+
initialColor = selectedColor,
547+
onColorChanged = { selectedColor = it },
548+
showPreview = false
549+
)
550+
}
551+
Spacer(Modifier.padding(bottom = WindowInsets.navigationBars.asPaddingValues().calculateBottomPadding()))
541552
}
542553
}
543554

iosApp/iosApp/Info.plist

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
<key>CFBundleShortVersionString</key>
1818
<string>1.0.5</string>
1919
<key>CFBundleVersion</key>
20-
<string>565</string>
20+
<string>567</string>
2121
<key>LSRequiresIPhoneOS</key>
2222
<true/>
2323
<key>CADisableMinimumFrameDurationOnPhone</key>

miuix/src/commonMain/kotlin/top/yukonga/miuix/kmp/extra/SuperBottomSheet.kt

Lines changed: 108 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ import androidx.compose.ui.text.style.TextAlign
4343
import androidx.compose.ui.unit.Dp
4444
import androidx.compose.ui.unit.DpSize
4545
import androidx.compose.ui.unit.dp
46+
import androidx.compose.ui.util.lerp
4647
import kotlinx.coroutines.launch
4748
import top.yukonga.miuix.kmp.basic.Text
4849
import top.yukonga.miuix.kmp.theme.MiuixTheme
@@ -182,15 +183,15 @@ private fun SuperBottomSheetContent(
182183
WindowInsets.statusBars.getTop(density).toDp()
183184
}
184185

185-
val rootBoxModifier = remember(onDismissRequest) {
186-
Modifier
187-
.pointerInput(onDismissRequest) {
188-
detectTapGestures(
189-
onTap = { onDismissRequest?.invoke() }
190-
)
191-
}
192-
.fillMaxSize()
193-
}
186+
val rootBoxModifier = Modifier
187+
.pointerInput(onDismissRequest) {
188+
detectTapGestures(
189+
onTap = {
190+
onDismissRequest?.invoke()
191+
}
192+
)
193+
}
194+
.fillMaxSize()
194195

195196
Box(modifier = rootBoxModifier) {
196197
SuperBottomSheetColumn(
@@ -241,10 +242,31 @@ private fun SuperBottomSheetColumn(
241242
) {
242243
val coroutineScope = rememberCoroutineScope()
243244

245+
// Calculate the overscroll offset for background fill
246+
val dragOffsetYValue by remember { derivedStateOf { dragOffsetY.value } }
247+
val overscrollOffsetPx by remember {
248+
derivedStateOf {
249+
(-dragOffsetYValue).coerceAtLeast(0f)
250+
}
251+
}
252+
244253
Box(
245254
modifier = Modifier.fillMaxSize(),
246255
contentAlignment = Alignment.BottomCenter
247256
) {
257+
// Background fill for the area revealed when dragging up (overscroll effect)
258+
if (overscrollOffsetPx > 0f) {
259+
Box(
260+
modifier = Modifier
261+
.align(Alignment.BottomCenter)
262+
.widthIn(max = sheetMaxWidth)
263+
.fillMaxWidth()
264+
.height(with(density) { overscrollOffsetPx.toDp() })
265+
.padding(horizontal = outsideMargin.width)
266+
.background(backgroundColor)
267+
)
268+
}
269+
248270
Column(
249271
modifier = modifier
250272
.pointerInput(Unit) {
@@ -308,6 +330,11 @@ private fun DragHandleArea(
308330
coroutineScope: kotlinx.coroutines.CoroutineScope,
309331
onDismissRequest: (() -> Unit)?
310332
) {
333+
val dragStartOffset = remember { mutableFloatStateOf(0f) }
334+
val isPressing = remember { mutableFloatStateOf(0f) }
335+
val pressScale = remember { Animatable(1f) }
336+
val pressWidth = remember { Animatable(45f) }
337+
311338
Box(
312339
modifier = Modifier
313340
.fillMaxWidth()
@@ -316,39 +343,91 @@ private fun DragHandleArea(
316343
detectVerticalDragGestures(
317344
onDragStart = {
318345
coroutineScope.launch {
346+
dragStartOffset.floatValue = dragOffsetY.value
319347
dragOffsetY.snapTo(dragOffsetY.value)
348+
// Animate press effect
349+
isPressing.floatValue = 1f
350+
launch {
351+
pressScale.animateTo(
352+
targetValue = 1.15f,
353+
animationSpec = tween(durationMillis = 100)
354+
)
355+
}
356+
launch {
357+
pressWidth.animateTo(
358+
targetValue = 55f,
359+
animationSpec = tween(durationMillis = 100)
360+
)
361+
}
320362
}
321363
},
322364
onDragEnd = {
323365
coroutineScope.launch {
366+
// Reset press effect
367+
isPressing.floatValue = 0f
368+
launch {
369+
pressScale.animateTo(
370+
targetValue = 1f,
371+
animationSpec = tween(durationMillis = 150)
372+
)
373+
}
374+
launch {
375+
pressWidth.animateTo(
376+
targetValue = 45f,
377+
animationSpec = tween(durationMillis = 150)
378+
)
379+
}
380+
381+
val currentOffset = dragOffsetY.value
382+
val dragDelta = currentOffset - dragStartOffset.floatValue
383+
324384
when {
325-
// Dragged down significantly -> dismiss with animation
326-
dragOffsetY.value > 150f -> {
327-
// Animate to bottom of screen
385+
// Dragged down significantly -> dismiss
386+
dragDelta > 150f -> {
328387
onDismissRequest?.invoke()
388+
val windowHeightPx = windowHeight.value * density.density
329389
dragOffsetY.animateTo(
330-
targetValue = windowHeight.value * density.density,
390+
targetValue = windowHeightPx,
331391
animationSpec = tween(durationMillis = 250)
332392
)
333393
}
334-
// Reset position if no action triggered
394+
// Reset to original position (including overscroll bounce back)
335395
else -> {
336-
dragOffsetY.animateTo(0f, animationSpec = tween(durationMillis = 150))
337-
// Reset dim alpha
396+
dragOffsetY.animateTo(
397+
targetValue = 0f,
398+
animationSpec = tween(durationMillis = 250)
399+
)
338400
dimAlpha.value = 1f
339401
}
340402
}
341403
}
342404
},
343405
onVerticalDrag = { _, dragAmount ->
344406
coroutineScope.launch {
345-
// Only allow dragging down (positive offset)
346-
val newOffset = (dragOffsetY.value + dragAmount).coerceAtLeast(0f)
347-
dragOffsetY.snapTo(newOffset)
407+
val newOffset = dragOffsetY.value + dragAmount
348408

349-
// Update dim alpha based on sheet height
409+
// Apply damping effect when dragging upward (negative offset)
410+
val finalOffset = if (newOffset < 0) {
411+
// Overscroll effect: reduce drag amount with damping
412+
val dampingFactor = 0.1f // Adjust this value for more/less resistance
413+
val dampedAmount = dragAmount * dampingFactor
414+
(dragOffsetY.value + dampedAmount).coerceAtMost(0f)
415+
} else {
416+
// Normal drag downward
417+
newOffset
418+
}
419+
420+
dragOffsetY.snapTo(finalOffset)
421+
422+
// Update dim alpha based on downward drag only
350423
val thresholdPx = if (sheetHeightPx.value > 0) sheetHeightPx.value.toFloat() else 500f
351-
val alpha = 1f - (newOffset / thresholdPx).coerceIn(0f, 1f)
424+
val alpha = if (finalOffset >= 0) {
425+
// Dragging down - reduce alpha
426+
1f - (finalOffset / thresholdPx).coerceIn(0f, 1f)
427+
} else {
428+
// Dragging up or at base position - keep alpha at 1
429+
1f
430+
}
352431
dimAlpha.value = alpha
353432
}
354433
}
@@ -357,12 +436,17 @@ private fun DragHandleArea(
357436
contentAlignment = Alignment.Center
358437
) {
359438
// Drag handle indicator
439+
val handleAlpha = lerp(0.2f, 0.35f, isPressing.floatValue)
440+
360441
Box(
361442
modifier = Modifier
362-
.width(45.dp)
443+
.width(pressWidth.value.dp)
363444
.height(4.dp)
445+
.graphicsLayer {
446+
scaleY = pressScale.value
447+
}
364448
.clip(G2RoundedCornerShape(2.dp))
365-
.background(dragHandleColor)
449+
.background(dragHandleColor.copy(alpha = handleAlpha))
366450
)
367451
}
368452
}
@@ -434,5 +518,5 @@ object SuperBottomSheetDefaults {
434518
/**
435519
* The default margin inside the [SuperBottomSheet].
436520
*/
437-
val insideMargin = DpSize(24.dp, 24.dp)
521+
val insideMargin = DpSize(24.dp, 0.dp)
438522
}

0 commit comments

Comments
 (0)