Skip to content

Instantly share code, notes, and snippets.

@fergdev
Created September 30, 2023 21:55
Show Gist options
  • Save fergdev/b8255a604b0521c3d0701f8a3733742d to your computer and use it in GitHub Desktop.
Save fergdev/b8255a604b0521c3d0701f8a3733742d to your computer and use it in GitHub Desktop.
M3 - Compose Component Mash
package ferg.componentmash
import android.app.Activity
import android.os.Bundle
import androidx.activity.compose.setContent
import androidx.compose.animation.animateColorAsState
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.AddCircle
import androidx.compose.material.icons.filled.Done
import androidx.compose.material.icons.filled.Edit
import androidx.compose.material.icons.filled.ExitToApp
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material.icons.filled.Home
import androidx.compose.material.icons.filled.Info
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.AssistChip
import androidx.compose.material3.Badge
import androidx.compose.material3.BadgedBox
import androidx.compose.material3.BottomAppBar
import androidx.compose.material3.Button
import androidx.compose.material3.Card
import androidx.compose.material3.Checkbox
import androidx.compose.material3.DatePicker
import androidx.compose.material3.DatePickerDialog
import androidx.compose.material3.DatePickerState
import androidx.compose.material3.DateRangePicker
import androidx.compose.material3.DateRangePickerState
import androidx.compose.material3.DismissValue
import androidx.compose.material3.DisplayMode
import androidx.compose.material3.Divider
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.ElevatedAssistChip
import androidx.compose.material3.ElevatedButton
import androidx.compose.material3.ElevatedCard
import androidx.compose.material3.ElevatedFilterChip
import androidx.compose.material3.ElevatedSuggestionChip
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ExposedDropdownMenuBox
import androidx.compose.material3.ExposedDropdownMenuDefaults
import androidx.compose.material3.ExtendedFloatingActionButton
import androidx.compose.material3.FilledIconButton
import androidx.compose.material3.FilledIconToggleButton
import androidx.compose.material3.FilledTonalButton
import androidx.compose.material3.FilledTonalIconButton
import androidx.compose.material3.FilledTonalIconToggleButton
import androidx.compose.material3.FilterChip
import androidx.compose.material3.FloatingActionButton
import androidx.compose.material3.FloatingActionButtonDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.IconToggleButton
import androidx.compose.material3.InputChip
import androidx.compose.material3.ListItem
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.OutlinedCard
import androidx.compose.material3.OutlinedIconButton
import androidx.compose.material3.OutlinedIconToggleButton
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.PlainTooltipBox
import androidx.compose.material3.PlainTooltipState
import androidx.compose.material3.RadioButton
import androidx.compose.material3.RangeSlider
import androidx.compose.material3.RichTooltipBox
import androidx.compose.material3.RichTooltipState
import androidx.compose.material3.Slider
import androidx.compose.material3.Snackbar
import androidx.compose.material3.SnackbarData
import androidx.compose.material3.SnackbarDuration
import androidx.compose.material3.SnackbarVisuals
import androidx.compose.material3.SuggestionChip
import androidx.compose.material3.Surface
import androidx.compose.material3.SwipeToDismiss
import androidx.compose.material3.Switch
import androidx.compose.material3.Tab
import androidx.compose.material3.TabRow
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.TextField
import androidx.compose.material3.TimeInput
import androidx.compose.material3.TimePicker
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TriStateCheckbox
import androidx.compose.material3.rememberDismissState
import androidx.compose.material3.rememberTimePickerState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.state.ToggleableState.Indeterminate
import androidx.compose.ui.state.ToggleableState.Off
import androidx.compose.ui.state.ToggleableState.On
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.Font
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import kotlinx.coroutines.launch
import org.joda.time.DateTime
class ComponentMash : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
AppTheme {
Surface {
ScreenContent()
}
}
}
}
}
object Dates {
val today: DateTime = DateTime.now()
val todayPlus5Days: DateTime = today.plusDays(5)
val todayMinusOneMonth: DateTime = today.minusMonths(1)
val todayPlusOneMonth: DateTime = today.plusMonths(1)
val todayMinus2Years: DateTime = today.minusYears(2)
val todayPlus2Years: DateTime = today.plusYears(2)
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun ScreenContent() {
val activity = LocalContext.current as? Activity
var datePickerVisible by remember { mutableStateOf(false) }
var dateRangePickerVisible by remember { mutableStateOf(false) }
var alertDialogVisible by remember { mutableStateOf(false) }
var bottomSheetVisible by remember { mutableStateOf(false) }
var timePickDialogVisible by remember { mutableStateOf(false) }
var timeInputDialogVisible by remember { mutableStateOf(false) }
Column {
TopAppBar(title = {
Text(
text = "App bar",
style = AppTheme.typography.titleLargeBold,
)
}, navigationIcon = {
IconButton(onClick = {
activity?.finish()
}) {
Icon(
imageVector = ImageVector.vectorResource(R.drawable.sg_icon_arrow_back_blue_24dp),
contentDescription = "Back"
)
}
}, actions = {
IconButton(onClick = { /*TODO*/ }) {
Icon(
imageVector = ImageVector.vectorResource(id = R.drawable.ic_xml),
contentDescription = null
)
}
IconButton(onClick = { /*TODO*/ }) {
Icon(
imageVector = ImageVector.vectorResource(id = R.drawable.ic_compose),
contentDescription = null
)
}
})
LazyColumn(
verticalArrangement = Arrangement.spacedBy(24.dp), modifier = Modifier.padding(8.dp)
) {
item {
Heading(text = "Badge")
Row(
modifier = Modifier
.padding(16.dp)
.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceAround
) {
BadgedBox(badge = { Badge { Text("8") } }) {
Icon(
Icons.Filled.Favorite, contentDescription = "Favorite"
)
}
BadgedBox(badge = { Badge { Text("4") } }) {
Icon(
Icons.Filled.Done, contentDescription = "Favorite"
)
}
BadgedBox(badge = { Badge { Text("200") } }) {
Icon(
Icons.Filled.Home, contentDescription = "Favorite"
)
}
}
}
item {
Heading(text = "Bottom app bar")
BottomAppBar(actions = {
Row(
horizontalArrangement = Arrangement.spacedBy(8.dp),
modifier = Modifier.padding(horizontal = 8.dp)
) {
Icon(
Icons.Filled.Favorite, contentDescription = "Favorite"
)
Icon(
Icons.Filled.Done, contentDescription = "Favorite"
)
Icon(
Icons.Filled.Home, contentDescription = "Favorite"
)
}
}, floatingActionButton = {
FloatingActionButton(onClick = {}) {
Icon(
imageVector = ImageVector.vectorResource(id = R.drawable.ic_xml),
contentDescription = null
)
}
})
}
item {
Heading(text = "Bottom sheet")
Button(onClick = { bottomSheetVisible = true }) {
Text(text = "Bottom sheet")
}
}
item {
Heading(text = "Buttons")
Column(
modifier = Modifier.fillMaxWidth(),
) {
Button(onClick = {}) {
Text(text = "Button")
}
ElevatedButton(onClick = {}) {
Text(text = "Elevated Button")
}
FilledTonalButton(onClick = {}) {
Text(text = "Filled Tonal Button")
}
OutlinedButton(onClick = {}) {
Text(text = "Outlined Button")
}
TextButton(onClick = {}) {
Text(text = "Text Button")
}
}
}
item {
Heading(text = "Cards")
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceAround
) {
Card {
Text(
modifier = Modifier.padding(16.dp), text = "Filled Card"
)
}
ElevatedCard {
Text(
modifier = Modifier.padding(16.dp), text = "Elevated Card"
)
}
OutlinedCard {
Text(
modifier = Modifier.padding(16.dp), text = "Outlined Card"
)
}
}
}
item {
Heading(text = "Check box")
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceEvenly
) {
var checked by remember { mutableStateOf(true) }
Row(verticalAlignment = Alignment.CenterVertically) {
Text(text = "Enabled")
Checkbox(checked = checked, onCheckedChange = { checked = it })
}
Row(verticalAlignment = Alignment.CenterVertically) {
Text(text = "Disabled O")
Checkbox(enabled = false, checked = false, onCheckedChange = {})
}
Row(verticalAlignment = Alignment.CenterVertically) {
Text(text = "Disabled x")
Checkbox(enabled = false, checked = true, onCheckedChange = {})
}
}
}
item {
Heading(text = "Check box tri-state")
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceEvenly,
verticalAlignment = Alignment.CenterVertically
) {
var state by remember { mutableStateOf(On) }
Text(text = "Enabled")
TriStateCheckbox(state = state, onClick = {
state = when (state) {
On -> Off
Off -> Indeterminate
Indeterminate -> On
}
})
Text(text = "O")
TriStateCheckbox(enabled = false, state = Off, onClick = null)
Text(text = "X")
TriStateCheckbox(enabled = false, state = On, onClick = null)
Text(text = "-")
TriStateCheckbox(enabled = false, state = Indeterminate, onClick = null)
}
}
item {
Heading(text = "Chips")
LazyRow(modifier = Modifier.fillMaxWidth()) {
item {
AssistChip(
onClick = {},
label = { Text(text = "Assist chip") },
leadingIcon = {
Icon(imageVector = Icons.Filled.Home, contentDescription = null)
},
trailingIcon = {
Icon(
imageVector = Icons.Filled.ExitToApp,
contentDescription = null
)
},
)
}
item {
AssistChip(
enabled = false,
onClick = {},
label = { Text(text = "Assist chip disabled") },
leadingIcon = {
Icon(imageVector = Icons.Filled.Home, contentDescription = null)
},
trailingIcon = {
Icon(
imageVector = Icons.Filled.ExitToApp,
contentDescription = null
)
},
)
}
}
LazyRow(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.spacedBy(8.dp)
) {
item {
ElevatedAssistChip(
onClick = {},
label = { Text(text = "ElevatedAssistChip chip") },
leadingIcon = {
Icon(imageVector = Icons.Filled.Home, contentDescription = null)
},
trailingIcon = {
Icon(
imageVector = Icons.Filled.ExitToApp,
contentDescription = null
)
},
)
}
item {
ElevatedAssistChip(
enabled = false,
onClick = {},
label = { Text(text = "ElevatedAssistChip chip disabled") },
leadingIcon = {
Icon(imageVector = Icons.Filled.Home, contentDescription = null)
},
trailingIcon = {
Icon(
imageVector = Icons.Filled.ExitToApp,
contentDescription = null
)
},
)
}
}
Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
FilterChip(
onClick = {},
selected = true,
label = { Text(text = "Filter chip X") },
leadingIcon = {
Icon(imageVector = Icons.Filled.Home, contentDescription = null)
},
trailingIcon = {
Icon(
imageVector = Icons.Filled.ExitToApp,
contentDescription = null
)
},
)
FilterChip(
onClick = {},
selected = false,
label = { Text(text = "Filter chip 0") },
leadingIcon = {
Icon(imageVector = Icons.Filled.Home, contentDescription = null)
},
trailingIcon = {
Icon(
imageVector = Icons.Filled.ExitToApp,
contentDescription = null
)
},
)
}
Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
ElevatedFilterChip(
onClick = {},
selected = true,
label = { Text(text = "Elevated Filter chip X") },
leadingIcon = {
Icon(imageVector = Icons.Filled.Home, contentDescription = null)
},
trailingIcon = {
Icon(
imageVector = Icons.Filled.ExitToApp,
contentDescription = null
)
},
)
ElevatedFilterChip(
onClick = {},
selected = false,
label = { Text(text = "Elevated Filter chip 0") },
leadingIcon = {
Icon(imageVector = Icons.Filled.Home, contentDescription = null)
},
trailingIcon = {
Icon(
imageVector = Icons.Filled.ExitToApp,
contentDescription = null
)
},
)
}
InputChip(
onClick = {},
selected = false,
label = { Text(text = "Input chip") },
leadingIcon = {
Icon(imageVector = Icons.Filled.Home, contentDescription = null)
},
trailingIcon = {
Icon(
imageVector = Icons.Filled.ExitToApp,
contentDescription = null
)
},
)
SuggestionChip(
onClick = {},
label = { Text(text = "Suggestion chip") },
)
ElevatedSuggestionChip(onClick = {},
label = { Text(text = "Elevated suggestion chip") })
}
item {
Heading(text = "Date picker")
Column {
Button(onClick = { datePickerVisible = true }) {
Text(text = "Show date picker")
}
}
}
item {
Heading(text = "Date range picker")
Column {
Button(onClick = { dateRangePickerVisible = true }) {
Text(text = "Show range date picker")
}
}
}
item {
Heading(text = "Dialogs - alert")
Button(onClick = { alertDialogVisible = true }) {
Text("Show alert dialog")
}
}
item {
Heading(text = "FAB")
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceAround
) {
FloatingActionButton(onClick = {}) {
Icon(
imageVector = ImageVector.vectorResource(id = R.drawable.ic_xml),
contentDescription = null
)
}
FloatingActionButton(
onClick = {}, shape = FloatingActionButtonDefaults.smallShape
) {
Icon(
imageVector = ImageVector.vectorResource(id = R.drawable.ic_xml),
contentDescription = null
)
}
FloatingActionButton(
onClick = {}, shape = FloatingActionButtonDefaults.largeShape
) {
Icon(
imageVector = ImageVector.vectorResource(id = R.drawable.ic_xml),
contentDescription = null
)
}
}
}
item {
Heading(text = "FAB extended")
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceAround
) {
ExtendedFloatingActionButton(onClick = {}) {
Text(text = "Navigate")
}
}
}
item {
Heading(text = "Icon Button")
Row(modifier = Modifier.fillMaxWidth()) {
IconButton(onClick = {}) {
Icon(
imageVector = Icons.Filled.Edit,
contentDescription = null
)
}
IconButton(onClick = {}, enabled = false) {
Icon(
imageVector = Icons.Filled.Edit,
contentDescription = null
)
}
}
}
item {
Heading(text = "Icon Toggle Button")
Row(modifier = Modifier.fillMaxWidth()) {
IconToggleButton(checked = true, onCheckedChange = {}) {
Icon(
imageVector = Icons.Filled.Edit,
contentDescription = null
)
}
IconToggleButton(checked = false, onCheckedChange = {}) {
Icon(
imageVector = Icons.Filled.Edit,
contentDescription = null
)
}
IconToggleButton(checked = true, enabled = false, onCheckedChange = {}) {
Icon(
imageVector = Icons.Filled.Edit,
contentDescription = null
)
}
IconToggleButton(checked = false, enabled = false, onCheckedChange = {}) {
Icon(
imageVector = Icons.Filled.Edit,
contentDescription = null
)
}
}
}
item {
Heading(text = "Filled Icon Button")
Row(modifier = Modifier.fillMaxWidth()) {
FilledIconButton(onClick = {}) {
Icon(
imageVector = Icons.Filled.Edit,
contentDescription = null
)
}
FilledIconButton(onClick = {}, enabled = false) {
Icon(
imageVector = Icons.Filled.Edit,
contentDescription = null
)
}
}
}
item {
Heading(text = "Filled Icon Toggle Button")
Row(modifier = Modifier.fillMaxWidth()) {
FilledIconToggleButton(onCheckedChange = {}, checked = true) {
Icon(
imageVector = Icons.Filled.Edit,
contentDescription = null
)
}
FilledIconToggleButton(onCheckedChange = {}, checked = false) {
Icon(
imageVector = Icons.Filled.Edit,
contentDescription = null
)
}
FilledIconToggleButton(onCheckedChange = {}, checked = true, enabled = false) {
Icon(
imageVector = Icons.Filled.Edit,
contentDescription = null
)
}
}
}
item {
Heading(text = "Filled Tonal Icon Button")
Row(modifier = Modifier.fillMaxWidth()) {
FilledTonalIconButton(onClick = {}) {
Icon(
imageVector = Icons.Filled.Edit,
contentDescription = null
)
}
FilledTonalIconButton(onClick = {}, enabled = false) {
Icon(
imageVector = Icons.Filled.Edit,
contentDescription = null
)
}
}
}
item {
Heading(text = "Filled Tonal Icon Toggle Button")
Row(modifier = Modifier.fillMaxWidth()) {
FilledTonalIconToggleButton(onCheckedChange = {}, checked = true) {
Icon(
imageVector = Icons.Filled.Edit,
contentDescription = null
)
}
FilledTonalIconToggleButton(onCheckedChange = {}, checked = false) {
Icon(
imageVector = Icons.Filled.Edit,
contentDescription = null
)
}
FilledTonalIconToggleButton(
onCheckedChange = {},
checked = true,
enabled = false
) {
Icon(
imageVector = Icons.Filled.Edit,
contentDescription = null
)
}
}
}
item {
Heading(text = "Filled Tonal Icon Toggle Button")
Row(modifier = Modifier.fillMaxWidth()) {
OutlinedIconButton(onClick = {}) {
Icon(
imageVector = Icons.Filled.Edit,
contentDescription = null
)
}
OutlinedIconButton(onClick = {}, enabled = false) {
Icon(
imageVector = Icons.Filled.Edit,
contentDescription = null
)
}
}
}
item {
Heading(text = "Filled Tonal Icon Toggle Button")
Row(modifier = Modifier.fillMaxWidth()) {
OutlinedIconToggleButton(onCheckedChange = {}, checked = true) {
Icon(
imageVector = Icons.Filled.Edit,
contentDescription = null
)
}
OutlinedIconToggleButton(onCheckedChange = {}, checked = false) {
Icon(
imageVector = Icons.Filled.Edit,
contentDescription = null
)
}
OutlinedIconToggleButton(
onCheckedChange = {},
checked = true,
enabled = false
) {
Icon(
imageVector = Icons.Filled.Edit,
contentDescription = null
)
}
}
}
item {
Heading(text = "List Item")
ListItem(leadingContent = {
Box(
Modifier
.width(40.dp)
.height(40.dp)
.background(
color = Color(0xFFF4D5C4),
shape = RoundedCornerShape(size = 100.dp)
),
contentAlignment = Alignment.Center
) {
Text(
text = "RA",
style = TextStyle(
fontSize = 14.sp,
lineHeight = 24.sp,
fontFamily = FontFamily(Font(R.font.serranopro)),
fontWeight = FontWeight(700),
color = Color(0xFFD14900),
textAlign = TextAlign.Center,
)
)
}
},
headlineContent = { Text(text = "List item") },
supportingContent = { Text(text = "Supporting content") },
trailingContent = {
Icon(
imageVector = ImageVector.vectorResource(id = R.drawable.sg_navigate_next_dn),
contentDescription = null
)
})
}
item {
Heading(text = "Menu - drop down")
var showMenu by remember { mutableStateOf(false) }
Box {
IconButton(onClick = { showMenu = !showMenu }) {
Icon(
imageVector = ImageVector.vectorResource(R.drawable.sg_icon_more),
contentDescription = null
)
}
DropdownMenu(expanded = showMenu, onDismissRequest = { showMenu = false }) {
DropdownMenuItem(
text = { Text(text = "Item 1") },
onClick = { showMenu = false },
leadingIcon = {
Icon(
imageVector = ImageVector.vectorResource(R.drawable.ic_xml),
contentDescription = null
)
},
trailingIcon = {
Icon(
imageVector = ImageVector.vectorResource(R.drawable.ic_compose),
contentDescription = null
)
},
)
DropdownMenuItem(
text = { Text(text = "Item 2") },
onClick = { showMenu = false },
leadingIcon = {
Icon(
imageVector = ImageVector.vectorResource(R.drawable.ic_xml),
contentDescription = null
)
},
trailingIcon = {
Icon(
imageVector = ImageVector.vectorResource(R.drawable.ic_compose),
contentDescription = null
)
},
)
DropdownMenuItem(
text = { Text(text = "Item 3") },
onClick = { showMenu = false },
leadingIcon = {
Icon(
imageVector = ImageVector.vectorResource(R.drawable.ic_xml),
contentDescription = null
)
},
trailingIcon = {
Icon(
imageVector = ImageVector.vectorResource(R.drawable.ic_compose),
contentDescription = null
)
},
)
}
}
}
item {
Heading(text = "Menu - exposed drop down")
val options = listOf("Option 1", "Option 2", "Option 3", "Option 4", "Option 5")
var expanded by remember { mutableStateOf(false) }
var selectedOptionText by remember { mutableStateOf(options[0]) }
ExposedDropdownMenuBox(
expanded = expanded,
onExpandedChange = { expanded = !expanded },
) {
TextField(
modifier = Modifier.menuAnchor(),
readOnly = true,
value = selectedOptionText,
onValueChange = {},
label = { Text("Label") },
trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = expanded) },
colors = ExposedDropdownMenuDefaults.textFieldColors(),
)
ExposedDropdownMenu(
expanded = expanded,
onDismissRequest = { expanded = false },
) {
options.forEach { selectionOption ->
DropdownMenuItem(
text = { Text(selectionOption) },
onClick = {
selectedOptionText = selectionOption
expanded = false
},
contentPadding = ExposedDropdownMenuDefaults.ItemContentPadding,
)
}
}
}
}
item {
Heading(text = "Menu - outlined exposed drop down")
val options = listOf("Option 1", "Option 2", "Option 3", "Option 4", "Option 5")
var expanded by remember { mutableStateOf(false) }
var selectedOptionText by remember { mutableStateOf(options[0]) }
ExposedDropdownMenuBox(
expanded = expanded,
onExpandedChange = { expanded = !expanded },
) {
OutlinedTextField(
modifier = Modifier.menuAnchor(),
readOnly = true,
value = selectedOptionText,
onValueChange = {},
label = { Text("Label") },
trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = expanded) },
// colors = ExposedDropdownMenuDefaults.textFieldColors(),
)
ExposedDropdownMenu(
expanded = expanded,
onDismissRequest = { expanded = false },
) {
options.forEach { selectionOption ->
DropdownMenuItem(
text = { Text(selectionOption) },
onClick = {
selectedOptionText = selectionOption
expanded = false
},
contentPadding = ExposedDropdownMenuDefaults.ItemContentPadding,
)
}
}
}
}
item {
Heading(text = "Radio button")
Row(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceEvenly
) {
var radioSelected by remember {
mutableStateOf(0)
}
Text(text = "Option A")
RadioButton(selected = radioSelected == 0, onClick = { radioSelected = 0 })
Text(text = "Option B")
RadioButton(selected = radioSelected == 1, onClick = { radioSelected = 1 })
Text(text = "Disabled")
RadioButton(enabled = false,
selected = radioSelected == 2,
onClick = { radioSelected = 2 })
}
}
item {
Heading(text = "Slider")
Column {
var value by remember { mutableStateOf(0.5f) }
Slider(value = value, onValueChange = { value = it })
Slider(value = 0.5f, onValueChange = {}, enabled = false)
var steppedValue by remember { mutableStateOf(5f) }
Slider(
value = steppedValue,
steps = 10,
onValueChange = { steppedValue = it })
Slider(
value = 0.4f, steps = 10, onValueChange = {}, enabled = false
)
}
}
item {
Heading(text = "Slider - ranged")
Column {
var value by remember { mutableStateOf(0.25f.rangeTo(0.75f)) }
RangeSlider(value = value, onValueChange = { value = it })
RangeSlider(
enabled = false,
value = 0.25f.rangeTo(0.75f),
onValueChange = { value = it })
}
}
item {
Heading(text = "SnackBar")
Column {
val snackbarData = object : SnackbarData {
override val visuals = object : SnackbarVisuals {
override val actionLabel: String
get() = "Action label"
override val duration: SnackbarDuration
get() = SnackbarDuration.Indefinite
override val message: String
get() = "Message"
override val withDismissAction: Boolean
get() = true
}
override fun performAction() {
}
override fun dismiss() {
}
}
Snackbar(snackbarData)
}
}
item {
Heading(text = "Swipe to dismiss")
val dismissState = rememberDismissState()
SwipeToDismiss(
state = dismissState,
background = {
val color by animateColorAsState(
when (dismissState.targetValue) {
DismissValue.Default -> Color.LightGray
DismissValue.DismissedToEnd -> AppTheme.sgColors.onSuccess
DismissValue.DismissedToStart -> AppTheme.sgColors.onWarning
}, label = ""
)
Box(
Modifier
.fillMaxSize()
.background(color)
)
},
dismissContent = {
Card {
ListItem(
headlineContent = {
Text("Headline content")
},
supportingContent = { Text("Swipe me left or right!") }
)
}
}
)
}
item {
Heading(text = "Switches")
Row {
var switchChecked by remember { mutableStateOf(true) }
Row(verticalAlignment = Alignment.CenterVertically) {
Text(text = "Switch", modifier = Modifier.padding(8.dp))
Switch(
checked = switchChecked,
onCheckedChange = { switchChecked = it })
}
var disabled by remember { mutableStateOf(true) }
Row(verticalAlignment = Alignment.CenterVertically) {
Text(text = "Disabled X", modifier = Modifier.padding(8.dp))
Switch(
enabled = false,
checked = disabled,
onCheckedChange = { disabled = it })
}
Row(verticalAlignment = Alignment.CenterVertically) {
Text(text = "Disabled O", modifier = Modifier.padding(8.dp))
Switch(
enabled = false,
checked = false,
onCheckedChange = { disabled = it })
}
}
}
item {
Heading(text = "Tabs")
var state by remember { mutableStateOf(0) }
val titles = listOf("Tab 1", "Tab 2", "Tab 3 with lots of text")
Column {
TabRow(selectedTabIndex = state) {
titles.forEachIndexed { index, title ->
Tab(
selected = state == index,
onClick = { state = index },
text = {
Text(
text = title,
maxLines = 2,
overflow = TextOverflow.Ellipsis
)
}
)
}
}
Text(
modifier = Modifier.align(Alignment.CenterHorizontally),
text = "Text tab ${state + 1} selected",
style = MaterialTheme.typography.bodyLarge
)
}
}
item {
Heading(text = "Text field")
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceEvenly
) {
var textField by remember { mutableStateOf("") }
val width = 125.dp
TextField(modifier = Modifier.width(width),
label = { Text(text = "Enabled") },
supportingText = { Text(text = "Supporting text") },
value = textField,
onValueChange = { textField = it })
var textField2 by remember { mutableStateOf("") }
TextField(modifier = Modifier.width(width),
label = { Text(text = "Error") },
isError = true,
supportingText = { Text(text = "Supporting text 2") },
value = textField2,
onValueChange = { textField2 = it })
TextField(modifier = Modifier.width(width),
label = { Text(text = "Disabled") },
enabled = false,
supportingText = { Text(text = "Supporting text 3") },
value = "",
onValueChange = {})
}
}
item {
Heading(text = "Text field - outlined")
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceEvenly
) {
var textField by remember { mutableStateOf("") }
val width = 125.dp
OutlinedTextField(modifier = Modifier.width(width),
label = { Text(text = "Enabled") },
supportingText = { Text(text = "Supporting text") },
value = textField,
onValueChange = { textField = it })
var textField2 by remember { mutableStateOf("") }
OutlinedTextField(modifier = Modifier.width(width),
label = { Text(text = "Error") },
isError = true,
supportingText = { Text(text = "Supporting text 2") },
value = textField2,
onValueChange = { textField2 = it })
OutlinedTextField(modifier = Modifier.width(width),
label = { Text(text = "Disabled") },
enabled = false,
supportingText = { Text(text = "Supporting text 3") },
value = "",
onValueChange = {})
}
}
item {
Heading(text = "Time picker")
Button(onClick = { timePickDialogVisible = true }) {
Text(text = "Show time picker")
}
}
item {
Heading(text = "Time input")
Button(onClick = { timeInputDialogVisible = true }) {
Text(text = "Show time input")
}
}
item {
Heading(text = "Tooltip")
PlainTooltipBox(
tooltip = { Text("Add to favorites") }
) {
IconButton(
onClick = { /* Icon button's click event */ },
modifier = Modifier
.wrapContentSize()
.tooltipAnchor()
) {
Icon(
imageVector = Icons.Filled.Favorite,
contentDescription = "Localized Description"
)
}
}
Text(text = "Press and hold")
}
item {
Heading(text = "Tooltip - manual invocation")
val tooltipState by remember { mutableStateOf(PlainTooltipState()) }
val scope = rememberCoroutineScope()
Column(
modifier = Modifier.fillMaxWidth(),
horizontalAlignment = Alignment.CenterHorizontally
) {
PlainTooltipBox(
tooltip = { Text("Add to list") },
tooltipState = tooltipState
) {
Icon(
imageVector = Icons.Filled.AddCircle,
contentDescription = "Localized Description"
)
}
OutlinedButton(
onClick = { scope.launch { tooltipState.show() } }
) {
Text("Display tooltip")
}
}
}
item {
Heading(text = "Rich tooltip")
val tooltipState by remember { mutableStateOf(RichTooltipState()) }
val scope = rememberCoroutineScope()
RichTooltipBox(
title = { Text("Add others") },
action = {
TextButton(
onClick = { scope.launch { tooltipState.dismiss() } }
) { Text("Learn more") }
},
text = { Text("Here is something really long text that will go into the rich tool and show off how this component works.") },
tooltipState = tooltipState
) {
IconButton(
onClick = { /* Icon button's click event */ },
modifier = Modifier.tooltipAnchor()
) {
Icon(
imageVector = Icons.Filled.Info,
contentDescription = "Localized Description"
)
}
}
Text(text = "Press and hold")
}
item {
Heading(text = "Rich tooltip - manual invocation")
val tooltipState by remember { mutableStateOf(RichTooltipState()) }
val scope = rememberCoroutineScope()
Column(
modifier = Modifier.fillMaxWidth(),
horizontalAlignment = Alignment.CenterHorizontally
) {
RichTooltipBox(
title = { Text("Add others") },
action = {
TextButton(
onClick = { scope.launch { tooltipState.dismiss() } }
) { Text("Learn more") }
},
text = { Text("Here is something really long text that will go into the rich tool and show off how this component works.") },
tooltipState = tooltipState
) {
IconButton(
onClick = { /* Icon button's click event */ },
) {
Icon(
imageVector = Icons.Filled.Info,
contentDescription = "Localized Description"
)
}
}
OutlinedButton(onClick = {
scope.launch { tooltipState.show() }
}) {
Text(text = "Display rich tool tip")
}
}
}
}
}
if (timeInputDialogVisible) {
val state = rememberTimePickerState(4, 20, false)
AlertDialog(onDismissRequest = { timeInputDialogVisible = false }) {
Surface {
Box(modifier = Modifier.padding(16.dp)) {
TimeInput(state = state)
}
}
}
}
if (timePickDialogVisible) {
val state = rememberTimePickerState(4, 20, false)
AlertDialog(onDismissRequest = { timePickDialogVisible = false }) {
Surface {
Box(modifier = Modifier.padding(16.dp)) {
TimePicker(state = state)
}
}
}
}
if (alertDialogVisible) {
AlertDialog(onDismissRequest = { alertDialogVisible = false }, confirmButton = {
Button(onClick = {
alertDialogVisible = false
}) { Text(text = "Confirm") }
}, dismissButton = {
Button(onClick = {
alertDialogVisible = false
}) { Text(text = "Dismiss") }
}, icon = {
Icon(
imageVector = ImageVector.vectorResource(id = R.drawable.ic_xml),
contentDescription = null
)
}, title = {
Text(text = "Title")
}, text = {
Text(text = "Here is the text of the dialog")
})
}
if (bottomSheetVisible) {
ModalBottomSheet(onDismissRequest = { bottomSheetVisible = false }) {
Spacer(modifier = Modifier.height(100.dp))
Text(text = "Here is a bottom sheet")
Spacer(modifier = Modifier.height(100.dp))
}
}
if (dateRangePickerVisible) {
val dateRangePickerState = DateRangePickerState(
initialSelectedStartDateMillis = Dates.today.millis,
initialSelectedEndDateMillis = Dates.todayPlus5Days.millis,
initialDisplayedMonthMillis = Dates.today.millis,
yearRange = IntRange(Dates.todayMinus2Years.year, Dates.todayPlus2Years.year),
initialDisplayMode = DisplayMode.Picker
)
DatePickerDialog(
onDismissRequest = { dateRangePickerVisible = false },
confirmButton = {
TextButton(onClick = { dateRangePickerVisible = false }) {
Text(text = "Confirm")
}
},
dismissButton = {
TextButton(onClick = { dateRangePickerVisible = false }) {
Text(text = "Dismiss")
}
}) {
DateRangePicker(state = dateRangePickerState, dateValidator = {
it > Dates.todayMinusOneMonth.millis && it < Dates.todayPlusOneMonth.millis
})
}
}
if (datePickerVisible) {
val datePickerState = DatePickerState(
initialDisplayedMonthMillis = Dates.today.millis,
initialSelectedDateMillis = Dates.today.millis,
yearRange = IntRange(
start = Dates.todayMinus2Years.year, endInclusive = Dates.todayPlus2Years.year
),
initialDisplayMode = DisplayMode.Picker
)
DatePickerDialog(onDismissRequest = { datePickerVisible = false }, confirmButton = {
TextButton(onClick = { datePickerVisible = false }) {
Text(text = "Confirm")
}
}, dismissButton = {
TextButton(onClick = { datePickerVisible = false }) {
Text(text = "Dismiss")
}
}) {
DatePicker(state = datePickerState, dateValidator = {
it > Dates.todayMinusOneMonth.millis && it < Dates.todayPlusOneMonth.millis
})
}
}
}
@Composable
private fun Heading(text: String) {
Divider(modifier = Modifier.fillMaxWidth())
Text(
text = text,
style = AppTheme.typography.titleLarge
)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment