From 2836b0b6974c8b323731e214995848548a236a96 Mon Sep 17 00:00:00 2001 From: howie Date: Fri, 18 Oct 2024 15:39:18 +0800 Subject: [PATCH 1/5] Modify the position of the popup --- .../top/yukonga/miuix/kmp/extra/SuperDropdown.kt | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) 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..daf3cdf8 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 @@ -190,6 +190,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 +222,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, @@ -353,7 +354,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 2495c0bd54a60e5d21bc8eeffb99eaa60aebce9e Mon Sep 17 00:00:00 2001 From: howie Date: Fri, 18 Oct 2024 17:09:35 +0800 Subject: [PATCH 2/5] Add: SuperDropdown will be "selected" when the popup is expanded. --- .../yukonga/miuix/kmp/extra/SuperDropdown.kt | 30 +++++++++++++++---- 1 file changed, 24 insertions(+), 6 deletions(-) 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 daf3cdf8..10bf4a96 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 @@ -4,6 +4,8 @@ import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.gestures.detectTapGestures +import androidx.compose.foundation.interaction.FocusInteraction +import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.WindowInsets @@ -21,6 +23,7 @@ import androidx.compose.foundation.layout.statusBars import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.windowInsetsPadding import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.material.ripple import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.MutableState @@ -112,6 +115,18 @@ fun SuperDropdown( var dropdownOffsetYPx by remember { mutableStateOf(0) } var componentHeightPx by remember { mutableStateOf(0) } var componentWidthPx by remember { mutableStateOf(0) } + val interactionSource = remember { MutableInteractionSource() } + val focus = remember { mutableStateOf(null) } + + LaunchedEffect(isDropdownExpanded.value) { + if (isDropdownExpanded.value) { + focus.value = FocusInteraction.Focus().also { + interactionSource.emit(it) + } + } else { + focus.value?.let { interactionSource.emit(FocusInteraction.Unfocus(it)) } + } + } BasicComponent( modifier = modifier @@ -134,6 +149,15 @@ fun SuperDropdown( componentHeightPx = coordinates.size.height componentWidthPx = coordinates.size.width } + } + .clickable( + interactionSource = interactionSource, + indication = ripple() + ) { + if (enabled) { + isDropdownExpanded.value = enabled + hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress) + } }, insideMargin = insideMargin, title = title, @@ -157,12 +181,6 @@ fun SuperDropdown( contentDescription = null ) }, - onClick = { - if (enabled) { - isDropdownExpanded.value = enabled - hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress) - } - }, enabled = enabled ) if (isDropdownExpanded.value) { From 3d14b3075d2f79d2d58bcfcd367479bff380a2c2 Mon Sep 17 00:00:00 2001 From: howie Date: Fri, 18 Oct 2024 23:40:13 +0800 Subject: [PATCH 3/5] update: [SuperDropdown] Change background instead of focus state when "selected". --- .../yukonga/miuix/kmp/extra/SuperDropdown.kt | 32 ++++++------------- 1 file changed, 10 insertions(+), 22 deletions(-) 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 10bf4a96..751e51dc 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 @@ -4,8 +4,6 @@ import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.gestures.detectTapGestures -import androidx.compose.foundation.interaction.FocusInteraction -import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.WindowInsets @@ -23,7 +21,6 @@ import androidx.compose.foundation.layout.statusBars import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.windowInsetsPadding import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.material.ripple import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.MutableState @@ -115,17 +112,10 @@ fun SuperDropdown( var dropdownOffsetYPx by remember { mutableStateOf(0) } var componentHeightPx by remember { mutableStateOf(0) } var componentWidthPx by remember { mutableStateOf(0) } - val interactionSource = remember { MutableInteractionSource() } - val focus = remember { mutableStateOf(null) } + val touchTint = remember { mutableStateOf(Color.Transparent) } - LaunchedEffect(isDropdownExpanded.value) { - if (isDropdownExpanded.value) { - focus.value = FocusInteraction.Focus().also { - interactionSource.emit(it) - } - } else { - focus.value?.let { interactionSource.emit(FocusInteraction.Unfocus(it)) } - } + isDropdownExpanded.value.let { + touchTint.value = if (it) MiuixTheme.colorScheme.touchTint else Color.Transparent } BasicComponent( @@ -150,15 +140,7 @@ fun SuperDropdown( componentWidthPx = coordinates.size.width } } - .clickable( - interactionSource = interactionSource, - indication = ripple() - ) { - if (enabled) { - isDropdownExpanded.value = enabled - hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress) - } - }, + .background(touchTint.value), insideMargin = insideMargin, title = title, titleColor = titleColor, @@ -181,6 +163,12 @@ fun SuperDropdown( contentDescription = null ) }, + onClick = { + if (enabled) { + isDropdownExpanded.value = enabled + hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress) + } + }, enabled = enabled ) if (isDropdownExpanded.value) { From 7d2a897f4a7e8609efef22773dcddb5267a6684a Mon Sep 17 00:00:00 2001 From: YuKongA <70465933+YuKongA@users.noreply.github.com> Date: Sat, 19 Oct 2024 11:23:40 +0800 Subject: [PATCH 4/5] Fix build --- .../yukonga/miuix/kmp/extra/SuperDropdown.kt | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) 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 751e51dc..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,16 +110,13 @@ 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) } var componentHeightPx by remember { mutableStateOf(0) } var componentWidthPx by remember { mutableStateOf(0) } - val touchTint = remember { mutableStateOf(Color.Transparent) } - - isDropdownExpanded.value.let { - touchTint.value = if (it) MiuixTheme.colorScheme.touchTint else Color.Transparent - } BasicComponent( modifier = modifier @@ -140,7 +140,7 @@ fun SuperDropdown( componentWidthPx = coordinates.size.width } } - .background(touchTint.value), + .background(touchTint), insideMargin = insideMargin, title = title, titleColor = titleColor, @@ -196,7 +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 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() @@ -245,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) @@ -365,8 +367,8 @@ fun calculateOffsetYPx( dropdownOffsetPx + componentHeightPx - insideHeightPx / 2 } else if (dropdownOffsetPx - statusBarPx > dropdownHeightPx) { // Show above - dropdownOffsetPx - dropdownHeightPx + insideHeightPx / 2 - } else if (windowHeightPx - statusBarPx - captionBarPx - navigationBarPx <= dropdownHeightPx) { + 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) { From 81ef4acbd163989d8ef20c937f2910a440971609 Mon Sep 17 00:00:00 2001 From: YuKongA <70465933+YuKongA@users.noreply.github.com> Date: Sat, 19 Oct 2024 11:35:54 +0800 Subject: [PATCH 5/5] example: No need for HorizontalPadding --- composeApp/src/commonMain/kotlin/SecondPage.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) 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 {