Skip to content

Commit 01bcc94

Browse files
committed
library: [SuperDropdown/SuperSpinner]: Optimize pressInteraction
1 parent 6e97982 commit 01bcc94

File tree

3 files changed

+92
-49
lines changed

3 files changed

+92
-49
lines changed

miuix/src/commonMain/kotlin/top/yukonga/miuix/kmp/basic/Component.kt

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,10 @@ import androidx.compose.foundation.layout.padding
1414
import androidx.compose.runtime.Composable
1515
import androidx.compose.runtime.Immutable
1616
import androidx.compose.runtime.Stable
17-
import androidx.compose.runtime.getValue
18-
import androidx.compose.runtime.mutableStateOf
1917
import androidx.compose.runtime.remember
20-
import androidx.compose.runtime.setValue
2118
import androidx.compose.ui.Alignment
2219
import androidx.compose.ui.Modifier
2320
import androidx.compose.ui.graphics.Color
24-
import androidx.compose.ui.input.pointer.PointerEventType
25-
import androidx.compose.ui.input.pointer.pointerInput
2621
import androidx.compose.ui.text.font.FontWeight
2722
import androidx.compose.ui.unit.dp
2823
import top.yukonga.miuix.kmp.theme.MiuixTheme
@@ -56,8 +51,6 @@ fun BasicComponent(
5651
enabled: Boolean = true,
5752
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }
5853
) {
59-
var pointerPressed by remember { mutableStateOf(false) }
60-
6154
Row(
6255
modifier = if (onClick != null && enabled) {
6356
modifier
@@ -70,14 +63,6 @@ fun BasicComponent(
7063
} else {
7164
modifier
7265
}
73-
.pointerInput(Unit) {
74-
awaitPointerEventScope {
75-
while (enabled) {
76-
val event = awaitPointerEvent()
77-
pointerPressed = event.type == PointerEventType.Press
78-
}
79-
}
80-
}
8166
.heightIn(min = 56.dp)
8267
.fillMaxWidth()
8368
.padding(insideMargin),

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

Lines changed: 46 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,9 @@ import androidx.compose.ui.unit.Dp
6666
import androidx.compose.ui.unit.LayoutDirection
6767
import androidx.compose.ui.unit.dp
6868
import androidx.compose.ui.unit.sp
69+
import kotlinx.coroutines.cancelAndJoin
70+
import kotlinx.coroutines.coroutineScope
71+
import kotlinx.coroutines.delay
6972
import kotlinx.coroutines.launch
7073
import top.yukonga.miuix.kmp.basic.BasicComponent
7174
import top.yukonga.miuix.kmp.basic.BasicComponentColors
@@ -80,8 +83,10 @@ import top.yukonga.miuix.kmp.theme.MiuixTheme
8083
import top.yukonga.miuix.kmp.utils.BackHandler
8184
import top.yukonga.miuix.kmp.utils.MiuixPopupUtil.Companion.dismissPopup
8285
import top.yukonga.miuix.kmp.utils.MiuixPopupUtil.Companion.showPopup
86+
import top.yukonga.miuix.kmp.utils.Platform
8387
import top.yukonga.miuix.kmp.utils.SmoothRoundedCornerShape
8488
import top.yukonga.miuix.kmp.utils.getWindowSize
89+
import top.yukonga.miuix.kmp.utils.platform
8590
import kotlin.math.roundToInt
8691

8792
/**
@@ -128,6 +133,8 @@ fun SuperDropdown(
128133
val held = remember { mutableStateOf<HoldDownInteraction.Hold?>(null) }
129134
val hapticFeedback = LocalHapticFeedback.current
130135
val actionColor = if (enabled) MiuixTheme.colorScheme.onSurfaceVariantActions else MiuixTheme.colorScheme.disabledOnSecondaryVariant
136+
137+
var pressInteraction: PressInteraction.Press? = null
131138
var alignLeft by rememberSaveable { mutableStateOf(true) }
132139
var componentInnerOffsetXPx by remember { mutableIntStateOf(0) }
133140
var componentInnerOffsetYPx by remember { mutableIntStateOf(0) }
@@ -166,29 +173,51 @@ fun SuperDropdown(
166173
)
167174
.pointerInput(Unit) {
168175
detectTapGestures(
169-
onPress = { position ->
176+
onPress = { offset ->
170177
if (enabled) {
171-
alignLeft = position.x < (size.width / 2)
172-
isDropdownPreExpand.value = true
173-
val pressInteraction = PressInteraction.Press(position)
174-
coroutineScope.launch {
175-
interactionSource.emit(pressInteraction)
176-
}
177-
val released = tryAwaitRelease()
178-
isDropdownPreExpand.value = false
179-
if (released) {
180-
isDropdownExpanded.value = enabled
181-
hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
182-
coroutineScope.launch {
178+
coroutineScope {
179+
val delayJob = launch {
180+
alignLeft = offset.x < (size.width / 2)
181+
isDropdownPreExpand.value = true
182+
delay(
183+
when (platform()) {
184+
Platform.IOS -> 150
185+
Platform.Android -> 100
186+
else -> 0
187+
}
188+
)
189+
val press = PressInteraction.Press(offset)
190+
interactionSource.emit(press)
191+
pressInteraction = press
192+
}
193+
val success = tryAwaitRelease()
194+
isDropdownPreExpand.value = false
195+
if (success) {
196+
isDropdownExpanded.value = enabled
197+
hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
183198
interactionSource.emit(HoldDownInteraction.Hold().also {
184199
held.value = it
185200
})
186-
interactionSource.emit(PressInteraction.Release(pressInteraction))
187201
}
188-
} else {
189-
coroutineScope.launch {
190-
interactionSource.emit(PressInteraction.Cancel(pressInteraction))
202+
if (delayJob.isActive) {
203+
delayJob.cancelAndJoin()
204+
if (success) {
205+
val press = PressInteraction.Press(offset)
206+
val release = PressInteraction.Release(press)
207+
interactionSource.emit(press)
208+
interactionSource.emit(release)
209+
}
210+
} else {
211+
pressInteraction?.let { pressInteraction ->
212+
val endInteraction = if (success) {
213+
PressInteraction.Release(pressInteraction)
214+
} else {
215+
PressInteraction.Cancel(pressInteraction)
216+
}
217+
interactionSource.emit(endInteraction)
218+
}
191219
}
220+
pressInteraction = null
192221
}
193222
}
194223
}

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

Lines changed: 46 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,9 @@ import androidx.compose.ui.unit.Dp
6666
import androidx.compose.ui.unit.DpSize
6767
import androidx.compose.ui.unit.LayoutDirection
6868
import androidx.compose.ui.unit.dp
69+
import kotlinx.coroutines.cancelAndJoin
70+
import kotlinx.coroutines.coroutineScope
71+
import kotlinx.coroutines.delay
6972
import kotlinx.coroutines.launch
7073
import top.yukonga.miuix.kmp.basic.BasicComponent
7174
import top.yukonga.miuix.kmp.basic.BasicComponentColors
@@ -82,8 +85,10 @@ import top.yukonga.miuix.kmp.utils.BackHandler
8285
import top.yukonga.miuix.kmp.utils.MiuixPopupUtil.Companion.dismissDialog
8386
import top.yukonga.miuix.kmp.utils.MiuixPopupUtil.Companion.dismissPopup
8487
import top.yukonga.miuix.kmp.utils.MiuixPopupUtil.Companion.showPopup
88+
import top.yukonga.miuix.kmp.utils.Platform
8589
import top.yukonga.miuix.kmp.utils.SmoothRoundedCornerShape
8690
import top.yukonga.miuix.kmp.utils.getWindowSize
91+
import top.yukonga.miuix.kmp.utils.platform
8792
import kotlin.math.roundToInt
8893

8994
/**
@@ -132,6 +137,8 @@ fun SuperSpinner(
132137
val held = remember { mutableStateOf<HoldDownInteraction.Hold?>(null) }
133138
val hapticFeedback = LocalHapticFeedback.current
134139
val actionColor = if (enabled) MiuixTheme.colorScheme.onSurfaceVariantActions else MiuixTheme.colorScheme.disabledOnSecondaryVariant
140+
141+
var pressInteraction: PressInteraction.Press? = null
135142
var alignLeft by rememberSaveable { mutableStateOf(true) }
136143
var componentInnerOffsetXPx by remember { mutableIntStateOf(0) }
137144
var componentInnerOffsetYPx by remember { mutableIntStateOf(0) }
@@ -170,29 +177,51 @@ fun SuperSpinner(
170177
)
171178
.pointerInput(Unit) {
172179
detectTapGestures(
173-
onPress = { position ->
180+
onPress = { offset ->
174181
if (enabled) {
175-
alignLeft = position.x < (size.width / 2)
176-
isDropdownPreExpand.value = true
177-
val pressInteraction = PressInteraction.Press(position)
178-
coroutineScope.launch {
179-
interactionSource.emit(pressInteraction)
180-
}
181-
val released = tryAwaitRelease()
182-
isDropdownPreExpand.value = false
183-
if (released) {
184-
isDropdownExpanded.value = enabled
185-
hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
186-
coroutineScope.launch {
182+
coroutineScope {
183+
val delayJob = launch {
184+
alignLeft = offset.x < (size.width / 2)
185+
isDropdownPreExpand.value = true
186+
delay(
187+
when (platform()) {
188+
Platform.IOS -> 150
189+
Platform.Android -> 100
190+
else -> 0
191+
}
192+
)
193+
val press = PressInteraction.Press(offset)
194+
interactionSource.emit(press)
195+
pressInteraction = press
196+
}
197+
val success = tryAwaitRelease()
198+
isDropdownPreExpand.value = false
199+
if (success) {
200+
isDropdownExpanded.value = enabled
201+
hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
187202
interactionSource.emit(HoldDownInteraction.Hold().also {
188203
held.value = it
189204
})
190-
interactionSource.emit(PressInteraction.Release(pressInteraction))
191205
}
192-
} else {
193-
coroutineScope.launch {
194-
interactionSource.emit(PressInteraction.Cancel(pressInteraction))
206+
if (delayJob.isActive) {
207+
delayJob.cancelAndJoin()
208+
if (success) {
209+
val press = PressInteraction.Press(offset)
210+
val release = PressInteraction.Release(press)
211+
interactionSource.emit(press)
212+
interactionSource.emit(release)
213+
}
214+
} else {
215+
pressInteraction?.let { pressInteraction ->
216+
val endInteraction = if (success) {
217+
PressInteraction.Release(pressInteraction)
218+
} else {
219+
PressInteraction.Cancel(pressInteraction)
220+
}
221+
interactionSource.emit(endInteraction)
222+
}
195223
}
224+
pressInteraction = null
196225
}
197226
}
198227
}

0 commit comments

Comments
 (0)