From 122732cc0a19c20f31491d4b238f76c012409ff7 Mon Sep 17 00:00:00 2001 From: Howie <40895875+HowieHChen@users.noreply.github.com> Date: Sat, 19 Oct 2024 11:40:19 +0800 Subject: [PATCH 1/2] library: Optimize SuperDropdown (#23) * Modify the position of the popup * Add: SuperDropdown will be "selected" when the popup is expanded. * update: [SuperDropdown] Change background instead of focus state when "selected". * example: No need for HorizontalPadding --------- Co-authored-by: YuKongA <70465933+YuKongA@users.noreply.github.com> --- .../src/commonMain/kotlin/SecondPage.kt | 3 +- .../yukonga/miuix/kmp/extra/SuperDropdown.kt | 30 +++++++++++++++---- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/composeApp/src/commonMain/kotlin/SecondPage.kt b/composeApp/src/commonMain/kotlin/SecondPage.kt index e3d5e2c..79d12a3 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 1dd411c..6eccf07 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 From d2f1a94e7a8548fee862469ae07964e492dd4959 Mon Sep 17 00:00:00 2001 From: YuKongA <70465933+YuKongA@users.noreply.github.com> Date: Sat, 19 Oct 2024 13:06:52 +0800 Subject: [PATCH 2/2] example: Add Card to Dropdown Page --- composeApp/src/commonMain/kotlin/MainPage.kt | 3 +- .../src/commonMain/kotlin/SecondPage.kt | 28 +++++++++++-------- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/composeApp/src/commonMain/kotlin/MainPage.kt b/composeApp/src/commonMain/kotlin/MainPage.kt index 8d4e564..9bba80c 100644 --- a/composeApp/src/commonMain/kotlin/MainPage.kt +++ b/composeApp/src/commonMain/kotlin/MainPage.kt @@ -55,7 +55,8 @@ fun MainPage( ) { item { SearchBar( - modifier = Modifier.padding(horizontal = 12.dp, vertical = 10.dp), + modifier = Modifier + .padding(start = 12.dp, end = 12.dp, top = 12.dp, bottom = 6.dp), inputField = { InputField( query = miuixSearchValue, diff --git a/composeApp/src/commonMain/kotlin/SecondPage.kt b/composeApp/src/commonMain/kotlin/SecondPage.kt index 79d12a3..46c4524 100644 --- a/composeApp/src/commonMain/kotlin/SecondPage.kt +++ b/composeApp/src/commonMain/kotlin/SecondPage.kt @@ -1,11 +1,11 @@ import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp +import top.yukonga.miuix.kmp.basic.Card import top.yukonga.miuix.kmp.basic.LazyColumn import top.yukonga.miuix.kmp.basic.ScrollBehavior import top.yukonga.miuix.kmp.extra.SuperDropdown @@ -22,17 +22,21 @@ fun SecondPage( contentPadding = PaddingValues(top = padding.calculateTopPadding()), topAppBarScrollBehavior = topAppBarScrollBehavior ) { - items(20) { - SuperDropdown( - title = "Dropdown", - summary = "Popup near click", - items = dropdownOptions, - selectedIndex = dropdownSelectedOption.value, - onSelectedIndexChange = { newOption -> dropdownSelectedOption.value = newOption } - ) - } item { - Spacer(modifier = Modifier.height(padding.calculateBottomPadding())) + Card( + modifier = Modifier + .padding(horizontal = 12.dp) + .padding(top = 12.dp, bottom = 12.dp + padding.calculateBottomPadding()) + ) { + for (i in 0 until 20) { + SuperDropdown( + title = "Dropdown", + items = dropdownOptions, + selectedIndex = dropdownSelectedOption.value, + onSelectedIndexChange = { newOption -> dropdownSelectedOption.value = newOption } + ) + } + } } } } \ No newline at end of file