0
# Input Components
1
2
Material Design input components optimized for iOS touch interactions, keyboard behavior, and accessibility standards.
3
4
## Capabilities
5
6
### TextField
7
8
Material text input field with iOS-optimized keyboard behavior and native integration.
9
10
```kotlin { .api }
11
/**
12
* Material Design filled text field with iOS keyboard integration
13
* Text fields allow users to enter and edit text
14
* @param value The input text to be shown in the text field
15
* @param onValueChange Called when the input service updates the text
16
* @param modifier Modifier to be applied to this text field
17
* @param enabled Controls the enabled state of this text field
18
* @param readOnly Controls the editable state of the text field
19
* @param textStyle The style to be applied to the input text
20
* @param label The optional label to be displayed inside the text field container
21
* @param placeholder The optional placeholder to be displayed when the text field is in focus and the input text is empty
22
* @param leadingIcon The optional leading icon to be displayed at the beginning of the text field container
23
* @param trailingIcon The optional trailing icon to be displayed at the end of the text field container
24
* @param isError Indicates if the text field's current value is in error state
25
* @param visualTransformation Transforms the visual representation of the input value
26
* @param keyboardOptions Software keyboard options that contains configuration such as KeyboardType and ImeAction
27
* @param keyboardActions When the input service emits an IME action, the corresponding callback is called
28
* @param singleLine When set to true, this text field becomes a single horizontally scrolling text field
29
* @param maxLines The maximum number of visible lines
30
* @param colors TextFieldColors that will be used to resolve the colors used for this text field
31
*/
32
@Composable
33
fun TextField(
34
value: String,
35
onValueChange: (String) -> Unit,
36
modifier: Modifier = Modifier,
37
enabled: Boolean = true,
38
readOnly: Boolean = false,
39
textStyle: TextStyle = LocalTextStyle.current,
40
label: @Composable (() -> Unit)? = null,
41
placeholder: @Composable (() -> Unit)? = null,
42
leadingIcon: @Composable (() -> Unit)? = null,
43
trailingIcon: @Composable (() -> Unit)? = null,
44
isError: Boolean = false,
45
visualTransformation: VisualTransformation = VisualTransformation.None,
46
keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
47
keyboardActions: KeyboardActions = KeyboardActions.Default,
48
singleLine: Boolean = false,
49
maxLines: Int = Int.MAX_VALUE,
50
colors: TextFieldColors = TextFieldDefaults.textFieldColors()
51
)
52
```
53
54
**Usage Examples:**
55
56
```kotlin
57
// Basic text field
58
var text by remember { mutableStateOf("") }
59
TextField(
60
value = text,
61
onValueChange = { text = it },
62
label = { Text("Enter text") }
63
)
64
65
// Password field with iOS-style visibility toggle
66
var password by remember { mutableStateOf("") }
67
var passwordVisible by remember { mutableStateOf(false) }
68
69
TextField(
70
value = password,
71
onValueChange = { password = it },
72
label = { Text("Password") },
73
visualTransformation = if (passwordVisible) VisualTransformation.None else PasswordVisualTransformation(),
74
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password),
75
trailingIcon = {
76
val image = if (passwordVisible) Icons.Filled.Visibility else Icons.Filled.VisibilityOff
77
IconButton(onClick = { passwordVisible = !passwordVisible }) {
78
Icon(imageVector = image, contentDescription = null)
79
}
80
}
81
)
82
83
// Email field with iOS keyboard optimization
84
var email by remember { mutableStateOf("") }
85
TextField(
86
value = email,
87
onValueChange = { email = it },
88
label = { Text("Email") },
89
keyboardOptions = KeyboardOptions(
90
keyboardType = KeyboardType.Email,
91
imeAction = ImeAction.Next
92
),
93
leadingIcon = {
94
Icon(Icons.Default.Email, contentDescription = null)
95
}
96
)
97
98
// Multi-line text field with iOS-style scrolling
99
var multilineText by remember { mutableStateOf("") }
100
TextField(
101
value = multilineText,
102
onValueChange = { multilineText = it },
103
label = { Text("Description") },
104
maxLines = 5,
105
modifier = Modifier.fillMaxWidth()
106
)
107
```
108
109
### OutlinedTextField
110
111
Text field with outlined border styling, following Material Design with iOS visual adaptations.
112
113
```kotlin { .api }
114
/**
115
* Material Design outlined text field with iOS-optimized border styling
116
* @param value The input text to be shown in the text field
117
* @param onValueChange Called when the input service updates the text
118
* @param modifier Modifier to be applied to this text field
119
* @param enabled Controls the enabled state of this text field
120
* @param readOnly Controls the editable state of the text field
121
* @param textStyle The style to be applied to the input text
122
* @param label The optional label to be displayed inside the text field container
123
* @param placeholder The optional placeholder to be displayed when the text field is in focus and the input text is empty
124
* @param leadingIcon The optional leading icon to be displayed at the beginning of the text field container
125
* @param trailingIcon The optional trailing icon to be displayed at the end of the text field container
126
* @param isError Indicates if the text field's current value is in error state
127
* @param visualTransformation Transforms the visual representation of the input value
128
* @param keyboardOptions Software keyboard options that contains configuration such as KeyboardType and ImeAction
129
* @param keyboardActions When the input service emits an IME action, the corresponding callback is called
130
* @param singleLine When set to true, this text field becomes a single horizontally scrolling text field
131
* @param maxLines The maximum number of visible lines
132
* @param colors TextFieldColors that will be used to resolve the colors used for this text field
133
*/
134
@Composable
135
fun OutlinedTextField(
136
value: String,
137
onValueChange: (String) -> Unit,
138
modifier: Modifier = Modifier,
139
enabled: Boolean = true,
140
readOnly: Boolean = false,
141
textStyle: TextStyle = LocalTextStyle.current,
142
label: @Composable (() -> Unit)? = null,
143
placeholder: @Composable (() -> Unit)? = null,
144
leadingIcon: @Composable (() -> Unit)? = null,
145
trailingIcon: @Composable (() -> Unit)? = null,
146
isError: Boolean = false,
147
visualTransformation: VisualTransformation = VisualTransformation.None,
148
keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
149
keyboardActions: KeyboardActions = KeyboardActions.Default,
150
singleLine: Boolean = false,
151
maxLines: Int = Int.MAX_VALUE,
152
colors: TextFieldColors = TextFieldDefaults.outlinedTextFieldColors()
153
)
154
```
155
156
### Checkbox
157
158
Material checkbox for boolean selection with iOS-style animation and accessibility.
159
160
```kotlin { .api }
161
/**
162
* Material Design checkbox with iOS-optimized touch targets and animations
163
* @param checked Whether this checkbox is checked or unchecked
164
* @param onCheckedChange Called when this checkbox is clicked
165
* @param modifier Modifier to be applied to this checkbox
166
* @param enabled Controls the enabled state of this checkbox
167
* @param colors CheckboxColors that will be used to resolve the colors used for this checkbox
168
*/
169
@Composable
170
fun Checkbox(
171
checked: Boolean,
172
onCheckedChange: ((Boolean) -> Unit)?,
173
modifier: Modifier = Modifier,
174
enabled: Boolean = true,
175
colors: CheckboxColors = CheckboxDefaults.colors()
176
)
177
```
178
179
**Usage Examples:**
180
181
```kotlin
182
// Basic checkbox
183
var isChecked by remember { mutableStateOf(false) }
184
Checkbox(
185
checked = isChecked,
186
onCheckedChange = { isChecked = it }
187
)
188
189
// Checkbox with label (iOS-style)
190
Row(
191
verticalAlignment = Alignment.CenterVertically,
192
modifier = Modifier
193
.fillMaxWidth()
194
.clickable { isChecked = !isChecked }
195
.padding(16.dp)
196
) {
197
Checkbox(
198
checked = isChecked,
199
onCheckedChange = { isChecked = it }
200
)
201
Spacer(modifier = Modifier.width(8.dp))
202
Text("Enable notifications")
203
}
204
205
// Custom colored checkbox
206
Checkbox(
207
checked = isChecked,
208
onCheckedChange = { isChecked = it },
209
colors = CheckboxDefaults.colors(
210
checkedColor = MaterialTheme.colors.secondary
211
)
212
)
213
```
214
215
### RadioButton
216
217
Single selection radio button with iOS-style visual feedback.
218
219
```kotlin { .api }
220
/**
221
* Material Design radio button with iOS-optimized selection states
222
* @param selected Whether this radio button is selected or unselected
223
* @param onClick Called when this radio button is clicked
224
* @param modifier Modifier to be applied to this radio button
225
* @param enabled Controls the enabled state of this radio button
226
* @param colors RadioButtonColors that will be used to resolve the colors used for this radio button
227
*/
228
@Composable
229
fun RadioButton(
230
selected: Boolean,
231
onClick: (() -> Unit)?,
232
modifier: Modifier = Modifier,
233
enabled: Boolean = true,
234
colors: RadioButtonColors = RadioButtonDefaults.colors()
235
)
236
```
237
238
**Usage Examples:**
239
240
```kotlin
241
// Radio button group
242
val options = listOf("Option 1", "Option 2", "Option 3")
243
var selectedOption by remember { mutableStateOf(options[0]) }
244
245
Column {
246
options.forEach { option ->
247
Row(
248
verticalAlignment = Alignment.CenterVertically,
249
modifier = Modifier
250
.fillMaxWidth()
251
.clickable { selectedOption = option }
252
.padding(horizontal = 16.dp, vertical = 8.dp)
253
) {
254
RadioButton(
255
selected = (option == selectedOption),
256
onClick = { selectedOption = option }
257
)
258
Spacer(modifier = Modifier.width(8.dp))
259
Text(text = option)
260
}
261
}
262
}
263
```
264
265
### Switch
266
267
Toggle switch component with iOS-style animations and haptic feedback integration.
268
269
```kotlin { .api }
270
/**
271
* Material Design switch with iOS-style toggle animations
272
* @param checked Whether or not this switch is checked
273
* @param onCheckedChange Called when this switch is clicked
274
* @param modifier Modifier to be applied to this switch
275
* @param enabled Controls the enabled state of this switch
276
* @param colors SwitchColors that will be used to resolve the colors used for this switch
277
*/
278
@Composable
279
fun Switch(
280
checked: Boolean,
281
onCheckedChange: ((Boolean) -> Unit)?,
282
modifier: Modifier = Modifier,
283
enabled: Boolean = true,
284
colors: SwitchColors = SwitchDefaults.colors()
285
)
286
```
287
288
**Usage Examples:**
289
290
```kotlin
291
// Basic switch
292
var isSwitchOn by remember { mutableStateOf(false) }
293
Switch(
294
checked = isSwitchOn,
295
onCheckedChange = { isSwitchOn = it }
296
)
297
298
// Switch with label (iOS settings style)
299
Row(
300
modifier = Modifier
301
.fillMaxWidth()
302
.padding(16.dp),
303
horizontalArrangement = Arrangement.SpaceBetween,
304
verticalAlignment = Alignment.CenterVertically
305
) {
306
Text("Dark Mode")
307
Switch(
308
checked = isSwitchOn,
309
onCheckedChange = { isSwitchOn = it }
310
)
311
}
312
313
// Custom styled switch
314
Switch(
315
checked = isSwitchOn,
316
onCheckedChange = { isSwitchOn = it },
317
colors = SwitchDefaults.colors(
318
checkedThumbColor = MaterialTheme.colors.secondary,
319
checkedTrackColor = MaterialTheme.colors.secondary.copy(alpha = 0.5f)
320
)
321
)
322
```
323
324
### Slider
325
326
Value selection slider with iOS-style thumb and track styling.
327
328
```kotlin { .api }
329
/**
330
* Material Design slider with iOS-optimized touch handling
331
* @param value Current value of the slider
332
* @param onValueChange Called when the value changes
333
* @param modifier Modifier to be applied to this slider
334
* @param enabled Controls the enabled state of this slider
335
* @param valueRange The range of values that this slider can take
336
* @param steps If greater than 0, specifies the amount of discrete allowable values
337
* @param onValueChangeFinished Called when value change has ended with a final value
338
* @param colors SliderColors that will be used to resolve the colors used for this slider
339
*/
340
@Composable
341
fun Slider(
342
value: Float,
343
onValueChange: (Float) -> Unit,
344
modifier: Modifier = Modifier,
345
enabled: Boolean = true,
346
valueRange: ClosedFloatingPointRange<Float> = 0f..1f,
347
steps: Int = 0,
348
onValueChangeFinished: (() -> Unit)? = null,
349
colors: SliderColors = SliderDefaults.colors()
350
)
351
```
352
353
**Usage Examples:**
354
355
```kotlin
356
// Basic slider
357
var sliderValue by remember { mutableStateOf(0.5f) }
358
Slider(
359
value = sliderValue,
360
onValueChange = { sliderValue = it }
361
)
362
363
// Volume slider with icons (iOS style)
364
Row(
365
modifier = Modifier
366
.fillMaxWidth()
367
.padding(16.dp),
368
verticalAlignment = Alignment.CenterVertically
369
) {
370
Icon(Icons.Default.VolumeDown, contentDescription = null)
371
Slider(
372
value = sliderValue,
373
onValueChange = { sliderValue = it },
374
modifier = Modifier.weight(1f),
375
colors = SliderDefaults.colors(
376
thumbColor = MaterialTheme.colors.primary,
377
activeTrackColor = MaterialTheme.colors.primary
378
)
379
)
380
Icon(Icons.Default.VolumeUp, contentDescription = null)
381
}
382
383
// Range slider with steps
384
var rangeSliderValue by remember { mutableStateOf(0.2f..0.8f) }
385
RangeSlider(
386
value = rangeSliderValue,
387
onValueChange = { rangeSliderValue = it },
388
valueRange = 0f..1f,
389
steps = 10
390
)
391
```
392
393
## Input Component Defaults and Utilities
394
395
```kotlin { .api }
396
object TextFieldDefaults {
397
fun textFieldColors(
398
textColor: Color = MaterialTheme.colors.onSurface,
399
disabledTextColor: Color = MaterialTheme.colors.onSurface.copy(alpha = ContentAlpha.disabled),
400
backgroundColor: Color = MaterialTheme.colors.onSurface.copy(alpha = 0.12f),
401
cursorColor: Color = MaterialTheme.colors.primary,
402
errorCursorColor: Color = MaterialTheme.colors.error,
403
focusedIndicatorColor: Color = MaterialTheme.colors.primary.copy(alpha = ContentAlpha.high),
404
unfocusedIndicatorColor: Color = MaterialTheme.colors.onSurface.copy(alpha = ContentAlpha.medium),
405
disabledIndicatorColor: Color = unfocusedIndicatorColor.copy(alpha = ContentAlpha.disabled),
406
errorIndicatorColor: Color = MaterialTheme.colors.error,
407
leadingIconColor: Color = MaterialTheme.colors.onSurface.copy(alpha = IconOpacity),
408
disabledLeadingIconColor: Color = leadingIconColor.copy(alpha = ContentAlpha.disabled),
409
errorLeadingIconColor: Color = leadingIconColor,
410
trailingIconColor: Color = MaterialTheme.colors.onSurface.copy(alpha = IconOpacity),
411
disabledTrailingIconColor: Color = trailingIconColor.copy(alpha = ContentAlpha.disabled),
412
errorTrailingIconColor: Color = MaterialTheme.colors.error,
413
focusedLabelColor: Color = MaterialTheme.colors.primary.copy(alpha = ContentAlpha.high),
414
unfocusedLabelColor: Color = MaterialTheme.colors.onSurface.copy(alpha = ContentAlpha.medium),
415
disabledLabelColor: Color = unfocusedLabelColor.copy(alpha = ContentAlpha.disabled),
416
errorLabelColor: Color = MaterialTheme.colors.error,
417
placeholderColor: Color = MaterialTheme.colors.onSurface.copy(alpha = ContentAlpha.medium),
418
disabledPlaceholderColor: Color = placeholderColor.copy(alpha = ContentAlpha.disabled)
419
): TextFieldColors
420
421
fun outlinedTextFieldColors(/* similar parameters */): TextFieldColors
422
}
423
424
object CheckboxDefaults {
425
fun colors(
426
checkedColor: Color = MaterialTheme.colors.secondary,
427
uncheckedColor: Color = MaterialTheme.colors.onSurface.copy(alpha = 0.6f),
428
checkmarkColor: Color = MaterialTheme.colors.surface,
429
disabledColor: Color = MaterialTheme.colors.onSurface.copy(alpha = ContentAlpha.disabled),
430
disabledIndeterminateColor: Color = checkedColor.copy(alpha = ContentAlpha.disabled)
431
): CheckboxColors
432
}
433
434
object RadioButtonDefaults {
435
fun colors(
436
selectedColor: Color = MaterialTheme.colors.secondary,
437
unselectedColor: Color = MaterialTheme.colors.onSurface.copy(alpha = 0.6f),
438
disabledColor: Color = MaterialTheme.colors.onSurface.copy(alpha = ContentAlpha.disabled)
439
): RadioButtonColors
440
}
441
442
object SwitchDefaults {
443
fun colors(
444
checkedThumbColor: Color = MaterialTheme.colors.secondaryVariant,
445
checkedTrackColor: Color = checkedThumbColor,
446
checkedTrackAlpha: Float = 0.54f,
447
uncheckedThumbColor: Color = MaterialTheme.colors.surface,
448
uncheckedTrackColor: Color = MaterialTheme.colors.onSurface,
449
uncheckedTrackAlpha: Float = 0.38f,
450
disabledCheckedThumbColor: Color = MaterialTheme.colors.surface,
451
disabledCheckedTrackColor: Color = MaterialTheme.colors.onSurface,
452
disabledUncheckedThumbColor: Color = disabledCheckedThumbColor,
453
disabledUncheckedTrackColor: Color = disabledCheckedTrackColor
454
): SwitchColors
455
}
456
457
object SliderDefaults {
458
fun colors(
459
thumbColor: Color = MaterialTheme.colors.primary,
460
disabledThumbColor: Color = MaterialTheme.colors.onSurface.copy(alpha = ContentAlpha.disabled),
461
activeTrackColor: Color = MaterialTheme.colors.primary,
462
inactiveTrackColor: Color = activeTrackColor.copy(alpha = 0.24f),
463
disabledActiveTrackColor: Color = MaterialTheme.colors.onSurface.copy(alpha = 0.32f),
464
disabledInactiveTrackColor: Color = disabledActiveTrackColor.copy(alpha = 0.12f),
465
activeTickColor: Color = contentColorFor(activeTrackColor).copy(alpha = 0.54f),
466
inactiveTickColor: Color = activeTrackColor.copy(alpha = 0.54f),
467
disabledActiveTickColor: Color = activeTickColor.copy(alpha = ContentAlpha.disabled),
468
disabledInactiveTickColor: Color = disabledActiveTrackColor.copy(alpha = ContentAlpha.disabled)
469
): SliderColors
470
}
471
472
// Visual transformation for password fields
473
class PasswordVisualTransformation(val mask: Char = '\u2022') : VisualTransformation
474
475
// Keyboard options for iOS optimization
476
data class KeyboardOptions(
477
val capitalization: KeyboardCapitalization = KeyboardCapitalization.None,
478
val autoCorrect: Boolean = true,
479
val keyboardType: KeyboardType = KeyboardType.Text,
480
val imeAction: ImeAction = ImeAction.Default
481
)
482
483
enum class KeyboardType {
484
Text, Ascii, Number, Phone, Uri, Email, Password, NumberPassword
485
}
486
487
enum class ImeAction {
488
Default, None, Go, Search, Send, Previous, Next, Done
489
}
490
```
491
492
### DropdownMenu
493
494
Material dropdown menu for displaying a list of selectable options with iOS-optimized positioning and animations.
495
496
```kotlin { .api }
497
/**
498
* Material Design dropdown menu with iOS-optimized presentation
499
* @param expanded Whether the dropdown menu is currently expanded and visible
500
* @param onDismissRequest Called when the user requests to dismiss the menu
501
* @param modifier Modifier to be applied to this dropdown menu
502
* @param offset DpOffset to be added to the position of the menu
503
* @param properties PopupProperties for further customization
504
* @param content The content of this dropdown menu, typically DropdownMenuItems
505
*/
506
@Composable
507
fun DropdownMenu(
508
expanded: Boolean,
509
onDismissRequest: () -> Unit,
510
modifier: Modifier = Modifier,
511
offset: DpOffset = DpOffset.Zero,
512
properties: PopupProperties = PopupProperties(focusable = true),
513
content: @Composable ColumnScope.() -> Unit
514
)
515
516
/**
517
* Material Design dropdown menu item with click handling and iOS touch feedback
518
* @param onClick Called when this menu item is clicked
519
* @param modifier Modifier to be applied to this menu item
520
* @param enabled Whether this menu item is enabled for selection
521
* @param contentPadding The spacing values to apply internally between the container and the content
522
* @param interactionSource The MutableInteractionSource representing the stream of interactions
523
* @param content The content to be displayed inside this menu item
524
*/
525
@Composable
526
fun DropdownMenuItem(
527
onClick: () -> Unit,
528
modifier: Modifier = Modifier,
529
enabled: Boolean = true,
530
contentPadding: PaddingValues = MenuDefaults.DropdownMenuItemContentPadding,
531
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
532
content: @Composable RowScope.() -> Unit
533
)
534
535
@Immutable
536
data class DpOffset(val x: Dp, val y: Dp) {
537
companion object {
538
val Zero = DpOffset(0.dp, 0.dp)
539
}
540
}
541
542
data class PopupProperties(
543
val focusable: Boolean = true,
544
val dismissOnBackPress: Boolean = true,
545
val dismissOnClickOutside: Boolean = true,
546
val securePolicy: SecureFlagPolicy = SecureFlagPolicy.Inherit,
547
val excludeFromSystemGesture: Boolean = true,
548
val clippingEnabled: Boolean = true
549
)
550
551
object MenuDefaults {
552
val DropdownMenuItemContentPadding: PaddingValues =
553
PaddingValues(horizontal = 16.dp, vertical = 12.dp)
554
}
555
```
556
557
**Usage Examples:**
558
559
```kotlin
560
// Basic dropdown menu
561
var expanded by remember { mutableStateOf(false) }
562
var selectedOption by remember { mutableStateOf("Select Option") }
563
val options = listOf("Option 1", "Option 2", "Option 3")
564
565
Box {
566
Button(
567
onClick = { expanded = true }
568
) {
569
Text(selectedOption)
570
Icon(
571
imageVector = Icons.Default.ArrowDropDown,
572
contentDescription = null
573
)
574
}
575
576
DropdownMenu(
577
expanded = expanded,
578
onDismissRequest = { expanded = false }
579
) {
580
options.forEach { option ->
581
DropdownMenuItem(
582
onClick = {
583
selectedOption = option
584
expanded = false
585
}
586
) {
587
Text(option)
588
}
589
}
590
}
591
}
592
593
// Dropdown menu with icons and dividers
594
DropdownMenu(
595
expanded = menuExpanded,
596
onDismissRequest = { menuExpanded = false }
597
) {
598
DropdownMenuItem(
599
onClick = {
600
// Handle edit action
601
menuExpanded = false
602
}
603
) {
604
Icon(
605
imageVector = Icons.Default.Edit,
606
contentDescription = null,
607
modifier = Modifier.size(18.dp)
608
)
609
Spacer(modifier = Modifier.width(8.dp))
610
Text("Edit")
611
}
612
613
DropdownMenuItem(
614
onClick = {
615
// Handle share action
616
menuExpanded = false
617
}
618
) {
619
Icon(
620
imageVector = Icons.Default.Share,
621
contentDescription = null,
622
modifier = Modifier.size(18.dp)
623
)
624
Spacer(modifier = Modifier.width(8.dp))
625
Text("Share")
626
}
627
628
Divider()
629
630
DropdownMenuItem(
631
onClick = {
632
// Handle delete action
633
menuExpanded = false
634
}
635
) {
636
Icon(
637
imageVector = Icons.Default.Delete,
638
contentDescription = null,
639
modifier = Modifier.size(18.dp),
640
tint = MaterialTheme.colors.error
641
)
642
Spacer(modifier = Modifier.width(8.dp))
643
Text(
644
text = "Delete",
645
color = MaterialTheme.colors.error
646
)
647
}
648
}
649
```