Skip to content

Commit b937a33

Browse files
committed
Update iOS radio button
1 parent 635a7b2 commit b937a33

10 files changed

Lines changed: 211 additions & 150 deletions

File tree

TODO.md

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
11
- add Input field into UIKit
22
- window size class common
33
- compact navigation bar
4-
- more native ios components
54
- update areas json
6-
7-
ios:
8-
- ios native: radiobutton

kmp/compose/common-ui/src/commonMain/kotlin/com/egoriku/grodnoroads/foundation/common/ui/dialog/ListItems.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package com.egoriku.grodnoroads.foundation.common.ui.dialog
22

33
import androidx.compose.foundation.clickable
4-
import androidx.compose.foundation.layout.Box
4+
import androidx.compose.foundation.layout.Column
55
import androidx.compose.foundation.layout.PaddingValues
66
import androidx.compose.foundation.layout.fillMaxWidth
77
import androidx.compose.foundation.lazy.LazyColumn
@@ -25,7 +25,7 @@ fun <T> ListItems(
2525
contentPadding = contentPadding
2626
) {
2727
itemsIndexed(list) { index, it ->
28-
Box(
28+
Column(
2929
modifier = Modifier
3030
.fillMaxWidth()
3131
.clickable(

kmp/compose/common-ui/src/commonMain/kotlin/com/egoriku/grodnoroads/foundation/common/ui/lazycolumn/SingleChoiceLazyColumn.kt

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,21 @@
11
package com.egoriku.grodnoroads.foundation.common.ui.lazycolumn
22

33
import androidx.compose.foundation.layout.PaddingValues
4+
import androidx.compose.foundation.layout.padding
5+
import androidx.compose.material3.HorizontalDivider
46
import androidx.compose.runtime.Composable
57
import androidx.compose.runtime.getValue
68
import androidx.compose.runtime.remember
79
import androidx.compose.runtime.setValue
810
import androidx.compose.ui.Modifier
11+
import androidx.compose.ui.tooling.preview.PreviewParameter
912
import androidx.compose.ui.unit.dp
1013
import com.egoriku.grodnoroads.foundation.common.ui.dialog.ListItems
1114
import com.egoriku.grodnoroads.foundation.core.rememberMutableIntState
1215
import com.egoriku.grodnoroads.foundation.preview.GrodnoRoadsM3ThemePreview
13-
import com.egoriku.grodnoroads.foundation.preview.PreviewGrodnoRoads
16+
import com.egoriku.grodnoroads.foundation.preview.PlatformPreviewProvider
17+
import com.egoriku.grodnoroads.foundation.preview.PreviewGrodnoRoadsDarkLight
18+
import com.egoriku.grodnoroads.foundation.theme.Platform
1419
import com.egoriku.grodnoroads.foundation.uikit.listitem.RadioButtonListItem
1520
import kotlinx.collections.immutable.ImmutableList
1621
import kotlinx.collections.immutable.toImmutableList
@@ -41,15 +46,18 @@ fun SingleChoiceLazyColumn(
4146
onSelect(index)
4247
}
4348
)
49+
HorizontalDivider()
4450
}
4551
}
4652

47-
@PreviewGrodnoRoads
53+
@PreviewGrodnoRoadsDarkLight
4854
@Composable
49-
private fun PreviewListSingleChoiceDialogPreview() = GrodnoRoadsM3ThemePreview {
55+
private fun PreviewListSingleChoiceDialogPreview(
56+
@PreviewParameter(PlatformPreviewProvider::class) platform: Platform
57+
) = GrodnoRoadsM3ThemePreview(platform = platform) {
5058
SingleChoiceLazyColumn(
59+
modifier = Modifier.padding(vertical = 8.dp),
5160
list = listOf("System", "Dark", "Light").toImmutableList(),
52-
contentPadding = PaddingValues(vertical = 16.dp),
5361
initialSelection = 0,
5462
onSelect = {}
5563
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package com.egoriku.grodnoroads.foundation.preview
2+
3+
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
4+
import com.egoriku.grodnoroads.foundation.theme.Platform
5+
6+
/**
7+
* A [PreviewParameterProvider] that supplies both [Platform.Android] and [Platform.IOS] values,
8+
* so a single preview function annotated with `@Preview` and
9+
* `@PreviewParameter(PlatformPreviewProvider::class)` will render once per platform.
10+
*
11+
* Usage:
12+
* ```kotlin
13+
* @Preview
14+
* @Composable
15+
* fun MyPreview(
16+
* @PreviewParameter(PlatformPreviewProvider::class) platform: Platform
17+
* ) {
18+
* GrodnoRoadsM3ThemePreview(platform = platform) {
19+
* MyComponent()
20+
* }
21+
* }
22+
* ```
23+
*/
24+
class PlatformPreviewProvider : PreviewParameterProvider<Platform> {
25+
override val values = sequenceOf(Platform.Android, Platform.IOS)
26+
}

kmp/compose/foundation/theme/src/iosMain/kotlin/com/egoriku/grodnoroads/foundation/theme/PlatformIndication.ios.kt

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,10 @@ import androidx.compose.material3.RippleConfiguration
1212
import androidx.compose.runtime.Composable
1313
import androidx.compose.runtime.Stable
1414
import androidx.compose.ui.Modifier
15-
import androidx.compose.ui.geometry.Offset
16-
import androidx.compose.ui.geometry.Rect
1715
import androidx.compose.ui.graphics.BlendMode
1816
import androidx.compose.ui.graphics.Color
19-
import androidx.compose.ui.graphics.Paint
2017
import androidx.compose.ui.graphics.drawscope.ContentDrawScope
21-
import androidx.compose.ui.graphics.drawscope.DrawScope
22-
import androidx.compose.ui.graphics.drawscope.drawIntoCanvas
2318
import androidx.compose.ui.graphics.drawscope.scale
24-
import androidx.compose.ui.graphics.withSaveLayer
2519
import androidx.compose.ui.node.DelegatableNode
2620
import androidx.compose.ui.node.DrawModifierNode
2721
import kotlinx.coroutines.launch
@@ -111,9 +105,7 @@ private class IOSPressIndicationNode(
111105
val currentAlpha = animatedAlpha.value
112106

113107
scale(scaleX = currentScale, scaleY = currentScale) {
114-
drawWithLayer {
115-
this@draw.drawContent()
116-
}
108+
this@draw.drawContent()
117109
}
118110

119111
// Apply alpha by drawing a semi-transparent overlay
@@ -124,12 +116,4 @@ private class IOSPressIndicationNode(
124116
)
125117
}
126118
}
127-
128-
private inline fun DrawScope.drawWithLayer(block: DrawScope.() -> Unit) {
129-
drawIntoCanvas { canvas ->
130-
canvas.withSaveLayer(Rect(Offset.Zero, size), Paint()) {
131-
block()
132-
}
133-
}
134-
}
135119
}
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
package com.egoriku.grodnoroads.foundation.uikit.dynamic
2+
3+
import androidx.compose.foundation.Canvas
4+
import androidx.compose.foundation.LocalIndication
5+
import androidx.compose.foundation.layout.Row
6+
import androidx.compose.foundation.layout.defaultMinSize
7+
import androidx.compose.foundation.layout.padding
8+
import androidx.compose.foundation.layout.requiredSize
9+
import androidx.compose.foundation.layout.wrapContentSize
10+
import androidx.compose.foundation.selection.selectable
11+
import androidx.compose.foundation.shape.CircleShape
12+
import androidx.compose.material3.MaterialTheme
13+
import androidx.compose.material3.RadioButton
14+
import androidx.compose.material3.RadioButtonDefaults
15+
import androidx.compose.material3.minimumInteractiveComponentSize
16+
import androidx.compose.runtime.Composable
17+
import androidx.compose.runtime.remember
18+
import androidx.compose.ui.Alignment
19+
import androidx.compose.ui.Modifier
20+
import androidx.compose.ui.draw.clip
21+
import androidx.compose.ui.graphics.Color
22+
import androidx.compose.ui.graphics.drawscope.Stroke
23+
import androidx.compose.ui.semantics.Role
24+
import androidx.compose.ui.tooling.preview.PreviewParameter
25+
import androidx.compose.ui.unit.dp
26+
import com.egoriku.grodnoroads.foundation.preview.GrodnoRoadsM3ThemePreview
27+
import com.egoriku.grodnoroads.foundation.preview.PlatformPreviewProvider
28+
import com.egoriku.grodnoroads.foundation.preview.PreviewGrodnoRoadsDarkLight
29+
import com.egoriku.grodnoroads.foundation.theme.LocalPlatform
30+
import com.egoriku.grodnoroads.foundation.theme.Platform
31+
import com.egoriku.grodnoroads.foundation.theme.Platform.Android
32+
import com.egoriku.grodnoroads.foundation.theme.Platform.IOS
33+
34+
@Composable
35+
fun DynamicRadioButton(
36+
selected: Boolean,
37+
modifier: Modifier = Modifier,
38+
enabled: Boolean = true,
39+
onClick: () -> Unit
40+
) {
41+
when (LocalPlatform.current) {
42+
Android -> {
43+
RadioButton(
44+
modifier = modifier,
45+
colors = RadioButtonDefaults.colors(
46+
selectedColor = MaterialTheme.colorScheme.secondary
47+
),
48+
enabled = enabled,
49+
selected = selected,
50+
onClick = onClick
51+
)
52+
}
53+
IOS -> {
54+
RadioButtonIos(
55+
selected = selected,
56+
modifier = modifier,
57+
enabled = enabled,
58+
onClick = onClick
59+
)
60+
}
61+
}
62+
}
63+
64+
@Composable
65+
private fun RadioButtonIos(
66+
selected: Boolean,
67+
modifier: Modifier = Modifier,
68+
enabled: Boolean = true,
69+
onClick: () -> Unit
70+
) {
71+
val checkCache = remember { CheckDrawingCache() }
72+
73+
val boxColor = when {
74+
!enabled && selected -> MaterialTheme.colorScheme.onSurface.copy(alpha = 0.38f)
75+
selected -> MaterialTheme.colorScheme.secondary
76+
else -> Color.Transparent
77+
}
78+
val checkmarkColor = when {
79+
!enabled -> Color.Transparent
80+
selected -> MaterialTheme.colorScheme.onSecondary
81+
else -> Color.Transparent
82+
}
83+
val borderColor = when {
84+
!enabled -> MaterialTheme.colorScheme.onSurface.copy(alpha = 0.38f)
85+
selected -> Color.Transparent
86+
else -> MaterialTheme.colorScheme.onSurfaceVariant
87+
}
88+
89+
Canvas(
90+
modifier = modifier
91+
.minimumInteractiveComponentSize()
92+
.defaultMinSize(24.dp, 24.dp)
93+
.padding(4.dp)
94+
.clip(CircleShape)
95+
.selectable(
96+
selected = selected,
97+
onClick = onClick,
98+
enabled = enabled,
99+
role = Role.RadioButton,
100+
interactionSource = null,
101+
indication = LocalIndication.current
102+
)
103+
.wrapContentSize(Alignment.Center)
104+
.requiredSize(24.dp)
105+
) {
106+
drawCircle(color = boxColor)
107+
drawCircle(
108+
color = borderColor,
109+
style = Stroke(width = 3.dp.toPx())
110+
)
111+
drawCheck(
112+
checkColor = checkmarkColor,
113+
checkFraction = if (selected) 1f else 0f,
114+
crossCenterGravitation = 0f,
115+
strokeWidthPx = 1.5.dp.toPx(),
116+
drawingCache = checkCache
117+
)
118+
}
119+
}
120+
121+
@PreviewGrodnoRoadsDarkLight
122+
@Composable
123+
private fun RadioButtonPreview(
124+
@PreviewParameter(PlatformPreviewProvider::class) platform: Platform
125+
) = GrodnoRoadsM3ThemePreview(platform = platform) {
126+
Row(modifier = Modifier.padding(16.dp)) {
127+
DynamicRadioButton(selected = true, onClick = {})
128+
DynamicRadioButton(selected = false, onClick = {})
129+
}
130+
}

kmp/compose/foundation/uikit/src/commonMain/kotlin/com/egoriku/grodnoroads/foundation/uikit/dynamic/RadioButton.kt

Lines changed: 0 additions & 111 deletions
This file was deleted.

0 commit comments

Comments
 (0)