Skip to content

Commit 73706fd

Browse files
committed
library: Fix Switch rounded corners & Optimize Switch touch logic
1 parent 2833c50 commit 73706fd

File tree

2 files changed

+75
-51
lines changed

2 files changed

+75
-51
lines changed

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

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ import androidx.compose.runtime.setValue
2121
import androidx.compose.ui.Alignment
2222
import androidx.compose.ui.Modifier
2323
import androidx.compose.ui.draw.clip
24-
import androidx.compose.ui.draw.drawBehind
2524
import androidx.compose.ui.geometry.CornerRadius
2625
import androidx.compose.ui.geometry.Offset
2726
import androidx.compose.ui.geometry.Size
@@ -141,9 +140,12 @@ fun SliderBackground(
141140
targetValue = if (isDragging) 0.044f else 0f,
142141
animationSpec = tween(150)
143142
).value
143+
144144
Canvas(
145-
modifier = modifier.clip(SmoothRoundedCornerShape(height)).background(backgroundColor)
146-
.drawBehind { drawRect(Color.Black.copy(alpha = backgroundAlpha)) }
145+
modifier = modifier
146+
.clip(SmoothRoundedCornerShape(height))
147+
.background(backgroundColor)
148+
.background(Color.Black.copy(alpha = backgroundAlpha))
147149
) {
148150
val barHeight = size.height
149151
val barWidth = size.width
@@ -190,7 +192,8 @@ class SliderColors(
190192
private val backgroundColor: Color
191193
) {
192194
@Stable
193-
internal fun foregroundColor(enabled: Boolean): Color = if (enabled) foregroundColor else disabledForegroundColor
195+
internal fun foregroundColor(enabled: Boolean): Color =
196+
if (enabled) foregroundColor else disabledForegroundColor
194197

195198
@Stable
196199
internal fun backgroundColor(): Color = backgroundColor

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

Lines changed: 68 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ import androidx.compose.runtime.setValue
2424
import androidx.compose.ui.Alignment
2525
import androidx.compose.ui.Modifier
2626
import androidx.compose.ui.draw.clip
27-
import androidx.compose.ui.draw.drawBehind
2827
import androidx.compose.ui.graphics.Color
2928
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
3029
import androidx.compose.ui.input.pointer.pointerInput
@@ -33,7 +32,6 @@ import androidx.compose.ui.semantics.Role
3332
import androidx.compose.ui.unit.Dp
3433
import androidx.compose.ui.unit.dp
3534
import top.yukonga.miuix.kmp.theme.MiuixTheme
36-
import top.yukonga.miuix.kmp.utils.SmoothRoundedCornerShape
3735
import kotlin.math.absoluteValue
3836

3937
/**
@@ -63,13 +61,14 @@ fun Switch(
6361
)
6462
}
6563
var isPressed by remember { mutableStateOf(false) }
66-
var dragOffset by remember { mutableStateOf(0f) }
64+
var trackDragOffset by remember { mutableStateOf(0f) }
65+
var thumbDragOffset by remember { mutableStateOf(0f) }
6766
val thumbOffset by animateDpAsState(
6867
targetValue = if (isChecked) {
69-
if (!enabled) 28.dp else if (isPressed) 26.5.dp else 28.dp
68+
if (!enabled) 26.dp else if (isPressed) 24.dp else 26.dp
7069
} else {
71-
if (!enabled) 4.dp else if (isPressed) 2.5.dp else 4.dp
72-
} + dragOffset.dp,
70+
if (!enabled) 4.dp else if (isPressed) 3.dp else 4.dp
71+
} + thumbDragOffset.dp,
7372
animationSpec = springSpec
7473
)
7574

@@ -108,63 +107,81 @@ fun Switch(
108107
Box(
109108
modifier = modifier
110109
.wrapContentSize(Alignment.Center)
111-
.size(52.dp, 28.5.dp)
112-
.requiredSize(52.dp, 28.5.dp)
113-
.clip(SmoothRoundedCornerShape(52.dp))
114-
.drawBehind { drawRect(backgroundColor) }
110+
.size(50.dp, 28.5.dp)
111+
.requiredSize(50.dp, 28.5.dp)
112+
.clip(RoundedCornerShape(100.dp))
113+
.background(backgroundColor)
115114
.pointerInput(Unit) {
116115
detectHorizontalDragGestures(
117-
onDragStart = {
118-
isPressed = true
119-
hasVibrated = false
120-
},
121116
onDragEnd = {
122-
isPressed = false
123-
val switchWidth = 24f
124-
if (dragOffset.absoluteValue > switchWidth / 2) {
125-
if (enabled) onCheckedChange?.invoke(!isChecked)
117+
if (trackDragOffset != 0f) {
118+
onCheckedChange?.invoke(!isChecked)
119+
if (thumbOffset == 4.dp || thumbOffset == 26.dp)
120+
hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
126121
}
127-
dragOffset = 0f
122+
trackDragOffset = 0f
128123
},
129124
onDragCancel = {
130-
isPressed = false
131-
dragOffset = 0f
132-
},
133-
onHorizontalDrag = { change, dragAmount ->
125+
trackDragOffset = 0f
126+
}
127+
) { change, dragAmount ->
128+
if (!enabled) return@detectHorizontalDragGestures
129+
trackDragOffset = dragAmount
130+
change.consume()
131+
}
132+
}
133+
.then(toggleableModifier)
134+
) {
135+
Box(
136+
modifier = Modifier
137+
.padding(start = thumbOffset)
138+
.align(Alignment.CenterStart)
139+
.size(thumbSize)
140+
.background(
141+
color = thumbColor,
142+
shape = RoundedCornerShape(100.dp)
143+
)
144+
.pointerInput(Unit) {
145+
detectHorizontalDragGestures(
146+
onDragStart = {
147+
isPressed = true
148+
hasVibrated = false
149+
},
150+
onDragEnd = {
151+
isPressed = false
152+
val switchWidth = 21f
153+
if (thumbDragOffset.absoluteValue > switchWidth / 2) {
154+
onCheckedChange?.invoke(!isChecked)
155+
}
156+
thumbDragOffset = 0f
157+
},
158+
onDragCancel = {
159+
isPressed = false
160+
thumbDragOffset = 0f
161+
}
162+
) { change, dragAmount ->
134163
if (!enabled) return@detectHorizontalDragGestures
135-
val newOffset = dragOffset + dragAmount / 2
136-
dragOffset =
137-
if (isChecked) newOffset.coerceIn(-24f, 0f) else newOffset.coerceIn(0f, 24f)
164+
val newOffset = thumbDragOffset + dragAmount / 2
165+
thumbDragOffset =
166+
if (isChecked) newOffset.coerceIn(-21f, 0f) else newOffset.coerceIn(0f, 21f)
138167
if (isChecked) {
139-
if (dragOffset in -23f..-1f) {
168+
if (thumbDragOffset in -20f..-1f) {
140169
hasVibrated = false
141-
} else if ((dragOffset == -24f || dragOffset == 0f) && !hasVibrated) {
170+
} else if ((thumbDragOffset == -21f || thumbDragOffset == 0f) && !hasVibrated) {
142171
hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
143172
hasVibrated = true
144173
}
145174
} else {
146-
if (dragOffset in 1f..23f) {
175+
if (thumbDragOffset in 1f..20f) {
147176
hasVibrated = false
148-
} else if ((dragOffset == 0f || dragOffset == 24f) && !hasVibrated) {
177+
} else if ((thumbDragOffset == 0f || thumbDragOffset == 21f) && !hasVibrated) {
149178
hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
150179
hasVibrated = true
151180
}
152181
}
153182
change.consume()
154183
}
155-
)
156-
}
157-
.then(toggleableModifier)
158-
) {
159-
Box(
160-
modifier = Modifier
161-
.padding(start = thumbOffset)
162-
.align(Alignment.CenterStart)
163-
.size(thumbSize)
164-
.background(
165-
color = thumbColor,
166-
shape = RoundedCornerShape(100.dp)
167-
)
184+
}
168185
)
169186
}
170187
}
@@ -210,14 +227,18 @@ class SwitchColors(
210227
private val disabledUncheckedTrackColor: Color
211228
) {
212229
@Stable
213-
internal fun checkedThumbColor(enabled: Boolean): Color = if (enabled) checkedThumbColor else disabledCheckedThumbColor
230+
internal fun checkedThumbColor(enabled: Boolean): Color =
231+
if (enabled) checkedThumbColor else disabledCheckedThumbColor
214232

215233
@Stable
216-
internal fun uncheckedThumbColor(enabled: Boolean): Color = if (enabled) uncheckedThumbColor else disabledUncheckedThumbColor
234+
internal fun uncheckedThumbColor(enabled: Boolean): Color =
235+
if (enabled) uncheckedThumbColor else disabledUncheckedThumbColor
217236

218237
@Stable
219-
internal fun checkedTrackColor(enabled: Boolean): Color = if (enabled) checkedTrackColor else disabledCheckedTrackColor
238+
internal fun checkedTrackColor(enabled: Boolean): Color =
239+
if (enabled) checkedTrackColor else disabledCheckedTrackColor
220240

221241
@Stable
222-
internal fun uncheckedTrackColor(enabled: Boolean): Color = if (enabled) uncheckedTrackColor else disabledUncheckedTrackColor
242+
internal fun uncheckedTrackColor(enabled: Boolean): Color =
243+
if (enabled) uncheckedTrackColor else disabledUncheckedTrackColor
223244
}

0 commit comments

Comments
 (0)