diff --git a/composeApp/src/commonMain/kotlin/SecondPage.kt b/composeApp/src/commonMain/kotlin/SecondPage.kt index e3d5e2cd..79d12a31 100644 --- a/composeApp/src/commonMain/kotlin/SecondPage.kt +++ b/composeApp/src/commonMain/kotlin/SecondPage.kt @@ -28,8 +28,7 @@ fun SecondPage( summary = "Popup near click", items = dropdownOptions, selectedIndex = dropdownSelectedOption.value, - onSelectedIndexChange = { newOption -> dropdownSelectedOption.value = newOption }, - horizontalPadding = 12.dp + onSelectedIndexChange = { newOption -> dropdownSelectedOption.value = newOption } ) } item { diff --git a/miuix/src/commonMain/kotlin/top/yukonga/miuix/kmp/extra/SuperDropdown.kt b/miuix/src/commonMain/kotlin/top/yukonga/miuix/kmp/extra/SuperDropdown.kt index 1dd411c4..6eccf074 100644 --- a/miuix/src/commonMain/kotlin/top/yukonga/miuix/kmp/extra/SuperDropdown.kt +++ b/miuix/src/commonMain/kotlin/top/yukonga/miuix/kmp/extra/SuperDropdown.kt @@ -1,5 +1,7 @@ package top.yukonga.miuix.kmp.extra +import androidx.compose.animation.animateColorAsState +import androidx.compose.animation.core.spring import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.clickable @@ -24,6 +26,7 @@ import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.MutableState +import androidx.compose.runtime.State import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateListOf import androidx.compose.runtime.mutableStateOf @@ -107,6 +110,8 @@ fun SuperDropdown( val isDropdownExpanded = remember { mutableStateOf(false) } val hapticFeedback = LocalHapticFeedback.current val actionColor = if (enabled) MiuixTheme.colorScheme.onSurfaceVariantActions else MiuixTheme.colorScheme.disabledOnSecondaryVariant + val targetColor = if (isDropdownExpanded.value) MiuixTheme.colorScheme.onBackground.copy(alpha = 0.15f) else Color.Transparent + val touchTint by animateColorAsState(targetValue = targetColor, animationSpec = spring(stiffness = 2000f)) var alignLeft by rememberSaveable { mutableStateOf(true) } var dropdownOffsetXPx by remember { mutableStateOf(0) } var dropdownOffsetYPx by remember { mutableStateOf(0) } @@ -134,7 +139,8 @@ fun SuperDropdown( componentHeightPx = coordinates.size.height componentWidthPx = coordinates.size.width } - }, + } + .background(touchTint), insideMargin = insideMargin, title = title, titleColor = titleColor, @@ -190,6 +196,7 @@ fun SuperDropdown( val captionBarPx by rememberUpdatedState( with(density) { WindowInsets.captionBar.asPaddingValues().calculateBottomPadding().toPx() }.roundToInt() ) + val insideWidthPx by rememberUpdatedState(with(density) { insideMargin.width.toPx() }.roundToInt()) val insideHeightPx by rememberUpdatedState(with(density) { insideMargin.height.toPx() }.roundToInt()) val displayCutoutLeftSize = rememberUpdatedState(with(density) { WindowInsets.displayCutout.asPaddingValues(density).calculateLeftPadding(LayoutDirection.Ltr).toPx() @@ -221,9 +228,9 @@ fun SuperDropdown( modifier = Modifier .onGloballyPositioned { layoutCoordinates -> offsetXPx = if (alwaysRight || !alignLeft) { - dropdownOffsetXPx + componentWidthPx - layoutCoordinates.size.width - paddingPx - if (defaultWindowInsetsPadding) displayCutoutLeftSize.value else 0 + dropdownOffsetXPx + componentWidthPx - insideWidthPx - layoutCoordinates.size.width - paddingPx - if (defaultWindowInsetsPadding) displayCutoutLeftSize.value else 0 } else { - dropdownOffsetXPx + paddingPx - if (defaultWindowInsetsPadding) displayCutoutLeftSize.value else 0 + dropdownOffsetXPx + paddingPx + insideWidthPx - if (defaultWindowInsetsPadding) displayCutoutLeftSize.value else 0 } offsetYPx = calculateOffsetYPx( windowHeightPx, @@ -238,8 +245,10 @@ fun SuperDropdown( } .align(AbsoluteAlignment.TopLeft) .graphicsLayer( - shadowElevation = 18f, - shape = SmoothRoundedCornerShape(18.dp) + shadowElevation = 40f, + shape = SmoothRoundedCornerShape(18.dp), + ambientShadowColor = MiuixTheme.colorScheme.onBackground.copy(alpha = 0.2f), + spotShadowColor = MiuixTheme.colorScheme.onBackground.copy(alpha = 0.6f) ) .clip(SmoothRoundedCornerShape(18.dp)) .background(MiuixTheme.colorScheme.surface) @@ -353,7 +362,16 @@ fun calculateOffsetYPx( navigationBarPx: Int, captionBarPx: Int ): Int { - return if (windowHeightPx - dropdownOffsetPx < dropdownHeightPx / 2 + captionBarPx + navigationBarPx + insideHeightPx + componentHeightPx / 2) { + return if (windowHeightPx - captionBarPx - navigationBarPx - dropdownOffsetPx - componentHeightPx > dropdownHeightPx) { + // Show below + dropdownOffsetPx + componentHeightPx - insideHeightPx / 2 + } else if (dropdownOffsetPx - statusBarPx > dropdownHeightPx) { + // Show above + dropdownOffsetPx - dropdownHeightPx + insideHeightPx / 2 + } else if (windowHeightPx - statusBarPx - captionBarPx - navigationBarPx <= dropdownHeightPx) { + // Special handling when the height of the popup is maxsize (== windowHeightPx) + 0 + } else if (windowHeightPx - dropdownOffsetPx < dropdownHeightPx / 2 + captionBarPx + navigationBarPx + insideHeightPx + componentHeightPx / 2) { windowHeightPx - dropdownHeightPx - insideHeightPx - captionBarPx - navigationBarPx } else { val offset = dropdownOffsetPx - dropdownHeightPx / 2 + componentHeightPx / 2