From cc73f312d9abbe969a4510cd3452b105f1571b98 Mon Sep 17 00:00:00 2001 From: Jamal Eason Date: Thu, 18 Jul 2024 08:39:47 -0700 Subject: [PATCH 1/8] Update CenterAlignedTopAppBar snippet to use centerAlignedTopAppBarColors --- .../main/java/com/example/compose/snippets/components/AppBar.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compose/snippets/src/main/java/com/example/compose/snippets/components/AppBar.kt b/compose/snippets/src/main/java/com/example/compose/snippets/components/AppBar.kt index 3df1e91f8..8199b00cd 100644 --- a/compose/snippets/src/main/java/com/example/compose/snippets/components/AppBar.kt +++ b/compose/snippets/src/main/java/com/example/compose/snippets/components/AppBar.kt @@ -204,7 +204,7 @@ fun CenterAlignedTopAppBarExample() { topBar = { CenterAlignedTopAppBar( - colors = TopAppBarDefaults.topAppBarColors( + colors = TopAppBarDefaults.centerAlignedTopAppBarColors( containerColor = MaterialTheme.colorScheme.primaryContainer, titleContentColor = MaterialTheme.colorScheme.primary, ), From 312340288cee5818c298267d2d6079352e1fc64b Mon Sep 17 00:00:00 2001 From: Jake Roseman <122034773+jakeroseman@users.noreply.github.com> Date: Mon, 22 Jul 2024 14:26:16 +0100 Subject: [PATCH 2/8] Time pickers comments (#295) * Adding advanced examples * Apply Spotless * Adding advanced examples * Rename AdvancedTimePickerExample * Rename AdvancedTimePickerExample --------- Co-authored-by: jakeroseman --- .../com/example/compose/snippets/components/TimePickers.kt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/compose/snippets/src/main/java/com/example/compose/snippets/components/TimePickers.kt b/compose/snippets/src/main/java/com/example/compose/snippets/components/TimePickers.kt index 5180a1bd8..129cbb053 100644 --- a/compose/snippets/src/main/java/com/example/compose/snippets/components/TimePickers.kt +++ b/compose/snippets/src/main/java/com/example/compose/snippets/components/TimePickers.kt @@ -144,6 +144,7 @@ fun DialExample( is24Hour = true, ) + // For information on how to implement a time picker dialog, see the "Dialogs for time pickers" guide. TimePickerDialog( onDismiss = { onDismiss() }, onConfirm = { onConfirm(timePickerState) } @@ -170,6 +171,7 @@ fun InputExample( is24Hour = true, ) + // For information on how to implement a time picker dialog, see the "Dialogs for time pickers" guide. TimePickerDialog( onDismiss = { onDismiss() }, onConfirm = { onConfirm(timePickerState) } @@ -207,6 +209,7 @@ fun AdvancedTimePickerExample( Icons.Filled.AccessTime } + // For information on how to implement a time picker dialog, see the "Dialogs for time pickers" guide. AdvancedTimePickerDialog( onDismiss = { onDismiss() }, onConfirm = { onConfirm(timePickerState) }, From 788f14dcac9f72a1a1871be528829926ff1d47ac Mon Sep 17 00:00:00 2001 From: Chiara Chiappini Date: Wed, 24 Jul 2024 14:42:49 +0100 Subject: [PATCH 3/8] Adds preview and breakpoint --- .../com/example/wear/snippets/list/List.kt | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/wear/src/main/java/com/example/wear/snippets/list/List.kt b/wear/src/main/java/com/example/wear/snippets/list/List.kt index 0c73de7d6..98cf8d187 100644 --- a/wear/src/main/java/com/example/wear/snippets/list/List.kt +++ b/wear/src/main/java/com/example/wear/snippets/list/List.kt @@ -18,6 +18,7 @@ package com.example.wear.snippets.list import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Build import androidx.compose.runtime.Composable +import androidx.compose.ui.platform.LocalConfiguration import androidx.wear.compose.material.Text import androidx.wear.compose.ui.tooling.preview.WearPreviewDevices import androidx.wear.compose.ui.tooling.preview.WearPreviewFontScales @@ -102,9 +103,38 @@ fun SnapAndFlingComposeList() { // [END android_wear_snap] } +// [START android_wear_list_breakpoint] +const val LARGE_DISPLAY_BREAKPOINT = 225 + +@Composable +fun isLargeDisplay() = LocalConfiguration.current.screenWidthDp >= LARGE_DISPLAY_BREAKPOINT +// [START_EXCLUDE] +@Composable +fun breakpointDemo() { + // [END_EXCLUDE] +// ... use in your Composables: + if (isLargeDisplay()) { + // Show additional content. + } else { + // Show content only for smaller displays. + } + // [START_EXCLUDE] +} +// [END_EXCLUDE] +// [END android_wear_list_breakpoint] + +// [START android_wear_list_preview] @WearPreviewDevices @WearPreviewFontScales @Composable fun ComposeListPreview() { ComposeList() } +// [END android_wear_list_preview] + +@WearPreviewDevices +@WearPreviewFontScales +@Composable +fun SnapAndFlingComposeListPreview() { + SnapAndFlingComposeList() +} From a84c80d425b31d72444a4d7157614899ee7df164 Mon Sep 17 00:00:00 2001 From: Alex Vanyo Date: Mon, 29 Jul 2024 03:00:18 -0700 Subject: [PATCH 4/8] Updating DeviceConfigurationOverride snippet comment (#232) --- .../DeviceConfigurationOverrideSnippets.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compose/snippets/src/androidTest/java/com/example/compose/snippets/deviceconfigurationoverride/DeviceConfigurationOverrideSnippets.kt b/compose/snippets/src/androidTest/java/com/example/compose/snippets/deviceconfigurationoverride/DeviceConfigurationOverrideSnippets.kt index 36db665a1..fca68ad4f 100644 --- a/compose/snippets/src/androidTest/java/com/example/compose/snippets/deviceconfigurationoverride/DeviceConfigurationOverrideSnippets.kt +++ b/compose/snippets/src/androidTest/java/com/example/compose/snippets/deviceconfigurationoverride/DeviceConfigurationOverrideSnippets.kt @@ -42,7 +42,7 @@ class DeviceConfigurationOverrideSnippetsTest { DeviceConfigurationOverride( DeviceConfigurationOverride.ForcedSize(DpSize(1280.dp, 800.dp)) ) { - MyScreen() // will be rendered in the space for 1280dp by 800dp without clipping + MyScreen() // Will be rendered in the space for 1280dp by 800dp without clipping. } } // [END android_compose_deviceconfigurationoverride_forcedsize] From 1a2f369e38bd5333d03f57df6daba6e158fa46d7 Mon Sep 17 00:00:00 2001 From: Jake Roseman <122034773+jakeroseman@users.noreply.github.com> Date: Mon, 29 Jul 2024 13:18:10 +0100 Subject: [PATCH 5/8] Timepickers redux (#296) * Reworking the time picker examples to be more friendly to copy-pasting * Apply Spotless * Updating the time picker examples to be more copy-pastable * Change in-use tag name back to the current form. * Apply Spotless * Renaming region tags * Renaming region tags --------- Co-authored-by: jakeroseman --- .../snippets/components/TimePickers.kt | 309 ++++++++++++------ 1 file changed, 218 insertions(+), 91 deletions(-) diff --git a/compose/snippets/src/main/java/com/example/compose/snippets/components/TimePickers.kt b/compose/snippets/src/main/java/com/example/compose/snippets/components/TimePickers.kt index 129cbb053..08f3c7aad 100644 --- a/compose/snippets/src/main/java/com/example/compose/snippets/components/TimePickers.kt +++ b/compose/snippets/src/main/java/com/example/compose/snippets/components/TimePickers.kt @@ -18,6 +18,7 @@ package com.example.compose.snippets.components 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.IntrinsicSize import androidx.compose.foundation.layout.Row @@ -60,79 +61,180 @@ import java.util.Locale @OptIn(ExperimentalMaterial3Api::class) @Composable fun TimePickerExamples() { + var showMenu by remember { mutableStateOf(true) } + var showDialExample by remember { mutableStateOf(false) } var showInputExample by remember { mutableStateOf(false) } + var showDialWithDialogExample by remember { mutableStateOf(false) } var showAdvancedExample by remember { mutableStateOf(false) } var selectedTime: TimePickerState? by remember { mutableStateOf(null) } val formatter = remember { SimpleDateFormat("hh:mm a", Locale.getDefault()) } - Column( - modifier = Modifier - .fillMaxSize() - .padding(32.dp), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.spacedBy(24.dp), + Box( + Modifier.fillMaxSize(), + contentAlignment = Alignment.Center ) { - Button(onClick = { - showDialExample = true - }) { - Text("Dial time picker") + if (showMenu) { + Column( + modifier = Modifier + .fillMaxSize() + .padding(32.dp), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.spacedBy(24.dp), + ) { + Button(onClick = { + showDialExample = true + showMenu = false + }) { + Text("Dial time picker") + } + Button(onClick = { + showInputExample = true + showMenu = false + }) { + Text("Input time picker") + } + Button(onClick = { + showDialWithDialogExample = true + showMenu = false + }) { + Text("Time picker with dialog") + } + Button(onClick = { + showAdvancedExample = true + showMenu = false + }) { + Text("Time picker with custom dialog") + } + if (selectedTime != null) { + val cal = Calendar.getInstance() + cal.set(Calendar.HOUR_OF_DAY, selectedTime!!.hour) + cal.set(Calendar.MINUTE, selectedTime!!.minute) + cal.isLenient = false + Text("Selected time = ${formatter.format(cal.time)}") + } else { + Text("No time selected.") + } + } } - Button(onClick = { - showInputExample = true - }) { - Text("Input time picker") + + when { + showDialExample -> DialUseStateExample( + onDismiss = { + showDialExample = false + showMenu = true + }, + onConfirm = { + time -> + selectedTime = time + showDialExample = false + showMenu = true + }, + ) + showInputExample -> InputUseStateExample( + onDismiss = { + showInputExample = false + showMenu = true + }, + onConfirm = { + time -> + selectedTime = time + showInputExample = false + showMenu = true + }, + ) + showDialWithDialogExample -> DialWithDialogExample( + onDismiss = { + showDialWithDialogExample = false + showMenu = true + }, + onConfirm = { + time -> + selectedTime = time + showDialWithDialogExample = false + showMenu = true + }, + ) + showAdvancedExample -> AdvancedTimePickerExample( + onDismiss = { + showAdvancedExample = false + showMenu = true + }, + onConfirm = { + time -> + selectedTime = time + showAdvancedExample = false + showMenu = true + }, + ) } - Button(onClick = { - showAdvancedExample = true - }) { - Text("Time picker with custom dialog") + } +} + +@OptIn(ExperimentalMaterial3Api::class) +// [START android_compose_components_dial] +@Composable +fun DialExample( + onConfirm: () -> Unit, + onDismiss: () -> Unit, +) { + val currentTime = Calendar.getInstance() + + val timePickerState = rememberTimePickerState( + initialHour = currentTime.get(Calendar.HOUR_OF_DAY), + initialMinute = currentTime.get(Calendar.MINUTE), + is24Hour = true, + ) + + Column { + TimePicker( + state = timePickerState, + ) + Button(onClick = onDismiss) { + Text("Dismiss picker") } - if (selectedTime != null) { - val cal = Calendar.getInstance() - cal.set(Calendar.HOUR_OF_DAY, selectedTime!!.hour) - cal.set(Calendar.MINUTE, selectedTime!!.minute) - cal.isLenient = false - Text("Selected time = ${formatter.format(cal.time)}") - } else { - Text("No time selected.") + Button(onClick = onConfirm) { + Text("Confirm selection") } } +} +// [END android_compose_components_dial] - when { - showDialExample -> DialExample( - onDismiss = { showDialExample = false }, - onConfirm = { - time -> - selectedTime = time - showDialExample = false - }, - ) - showInputExample -> InputExample( - onDismiss = { showInputExample = false }, - onConfirm = { - time -> - selectedTime = time - showInputExample = false - }, - ) - showAdvancedExample -> AdvancedTimePickerExample( - onDismiss = { showAdvancedExample = false }, - onConfirm = { - time -> - selectedTime = time - showAdvancedExample = false - }, +@OptIn(ExperimentalMaterial3Api::class) +// [START android_compose_components_input] +@Composable +fun InputExample( + onConfirm: () -> Unit, + onDismiss: () -> Unit, +) { + val currentTime = Calendar.getInstance() + + val timePickerState = rememberTimePickerState( + initialHour = currentTime.get(Calendar.HOUR_OF_DAY), + initialMinute = currentTime.get(Calendar.MINUTE), + is24Hour = true, + ) + + Column { + TimeInput( + state = timePickerState, ) + Button(onClick = onDismiss) { + Text("Dismiss picker") + } + Button(onClick = onConfirm) { + Text("Confirm selection") + } } } +// [END android_compose_components_input] @OptIn(ExperimentalMaterial3Api::class) -// [START android_compose_components_dial] +// [START android_compose_components_dial_usestate] @Composable -fun DialExample( +fun DialUseStateExample( onConfirm: (TimePickerState) -> Unit, onDismiss: () -> Unit, ) { @@ -144,22 +246,53 @@ fun DialExample( is24Hour = true, ) - // For information on how to implement a time picker dialog, see the "Dialogs for time pickers" guide. - TimePickerDialog( - onDismiss = { onDismiss() }, - onConfirm = { onConfirm(timePickerState) } - ) { + Column { TimePicker( state = timePickerState, ) + Button(onClick = onDismiss) { + Text("Dismiss picker") + } + Button(onClick = { onConfirm(timePickerState) }) { + Text("Confirm selection") + } } } -// [END android_compose_components_dial] +// [END android_compose_components_dial_usestate] @OptIn(ExperimentalMaterial3Api::class) -// [START android_compose_components_input] +// [START android_compose_components_input_usestate] @Composable -fun InputExample( +fun InputUseStateExample( + onConfirm: (TimePickerState) -> Unit, + onDismiss: () -> Unit, +) { + val currentTime = Calendar.getInstance() + + val timePickerState = rememberTimePickerState( + initialHour = currentTime.get(Calendar.HOUR_OF_DAY), + initialMinute = currentTime.get(Calendar.MINUTE), + is24Hour = true, + ) + + Column { + TimeInput( + state = timePickerState, + ) + Button(onClick = onDismiss) { + Text("Dismiss picker") + } + Button(onClick = { onConfirm(timePickerState) }) { + Text("Confirm selection") + } + } +} +// [END android_compose_components_input_usestate] + +@OptIn(ExperimentalMaterial3Api::class) +// [START android_compose_components_timepickerdialog] +@Composable +fun DialWithDialogExample( onConfirm: (TimePickerState) -> Unit, onDismiss: () -> Unit, ) { @@ -171,17 +304,38 @@ fun InputExample( is24Hour = true, ) - // For information on how to implement a time picker dialog, see the "Dialogs for time pickers" guide. TimePickerDialog( onDismiss = { onDismiss() }, onConfirm = { onConfirm(timePickerState) } ) { - TimeInput( + TimePicker( state = timePickerState, ) } } -// [END android_compose_components_input] + +@Composable +fun TimePickerDialog( + onDismiss: () -> Unit, + onConfirm: () -> Unit, + content: @Composable () -> Unit +) { + AlertDialog( + onDismissRequest = onDismiss, + dismissButton = { + TextButton(onClick = { onDismiss() }) { + Text("Dismiss") + } + }, + confirmButton = { + TextButton(onClick = { onConfirm() }) { + Text("OK") + } + }, + text = { content() } + ) +} +// [END android_compose_components_timepickerdialog] @OptIn(ExperimentalMaterial3Api::class) // [START android_compose_components_advanced] @@ -209,7 +363,6 @@ fun AdvancedTimePickerExample( Icons.Filled.AccessTime } - // For information on how to implement a time picker dialog, see the "Dialogs for time pickers" guide. AdvancedTimePickerDialog( onDismiss = { onDismiss() }, onConfirm = { onConfirm(timePickerState) }, @@ -233,33 +386,7 @@ fun AdvancedTimePickerExample( } } } -// [END android_compose_components_advanced] - -// [START android_compose_components_timepickerdialog] -@Composable -fun TimePickerDialog( - onDismiss: () -> Unit, - onConfirm: () -> Unit, - content: @Composable () -> Unit -) { - AlertDialog( - onDismissRequest = onDismiss, - dismissButton = { - TextButton(onClick = { onDismiss() }) { - Text("Dismiss") - } - }, - confirmButton = { - TextButton(onClick = { onConfirm() }) { - Text("OK") - } - }, - text = { content() } - ) -} -// [END android_compose_components_timepickerdialog] -// [START android_compose_components_advanceddialog] @Composable fun AdvancedTimePickerDialog( title: String = "Select Time", @@ -310,4 +437,4 @@ fun AdvancedTimePickerDialog( } } } -// [END android_compose_components_advanceddialog] +// [END android_compose_components_advanced] From e273661699880ab04ec52de5b6543a649310b0fc Mon Sep 17 00:00:00 2001 From: Jake Roseman <122034773+jakeroseman@users.noreply.github.com> Date: Thu, 1 Aug 2024 16:32:20 +0100 Subject: [PATCH 6/8] Date pickers (#302) * Reworking the time picker examples to be more friendly to copy-pasting * Apply Spotless * Updating the time picker examples to be more copy-pastable * Change in-use tag name back to the current form. * Apply Spotless * Renaming region tags * Renaming region tags * Adding date picker snippets * Apply Spotless * fixing region tags * Adding additional range tags --------- Co-authored-by: jakeroseman --- .../compose/snippets/SnippetsActivity.kt | 2 + .../snippets/components/DatePickers.kt | 315 ++++++++++++++++++ .../snippets/navigation/Destination.kt | 1 + 3 files changed, 318 insertions(+) create mode 100644 compose/snippets/src/main/java/com/example/compose/snippets/components/DatePickers.kt diff --git a/compose/snippets/src/main/java/com/example/compose/snippets/SnippetsActivity.kt b/compose/snippets/src/main/java/com/example/compose/snippets/SnippetsActivity.kt index 2e5de2bcb..aaed49166 100644 --- a/compose/snippets/src/main/java/com/example/compose/snippets/SnippetsActivity.kt +++ b/compose/snippets/src/main/java/com/example/compose/snippets/SnippetsActivity.kt @@ -34,6 +34,7 @@ import com.example.compose.snippets.components.ButtonExamples import com.example.compose.snippets.components.CheckboxExamples import com.example.compose.snippets.components.ChipExamples import com.example.compose.snippets.components.ComponentsScreen +import com.example.compose.snippets.components.DatePickerExamples import com.example.compose.snippets.components.DialogExamples import com.example.compose.snippets.components.DividerExamples import com.example.compose.snippets.components.FloatingActionButtonExamples @@ -105,6 +106,7 @@ class SnippetsActivity : ComponentActivity() { TopComponentsDestination.BadgeExamples -> BadgeExamples() TopComponentsDestination.PartialBottomSheet -> PartialBottomSheet() TopComponentsDestination.TimePickerExamples -> TimePickerExamples() + TopComponentsDestination.DatePickerExamples -> DatePickerExamples() } } } diff --git a/compose/snippets/src/main/java/com/example/compose/snippets/components/DatePickers.kt b/compose/snippets/src/main/java/com/example/compose/snippets/components/DatePickers.kt new file mode 100644 index 000000000..650b969a0 --- /dev/null +++ b/compose/snippets/src/main/java/com/example/compose/snippets/components/DatePickers.kt @@ -0,0 +1,315 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.compose.snippets.components + +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.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.offset +import androidx.compose.foundation.layout.padding +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.DateRange +import androidx.compose.material3.Button +import androidx.compose.material3.DatePicker +import androidx.compose.material3.DatePickerDialog +import androidx.compose.material3.DateRangePicker +import androidx.compose.material3.DisplayMode +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.OutlinedTextField +import androidx.compose.material3.Text +import androidx.compose.material3.TextButton +import androidx.compose.material3.rememberDatePickerState +import androidx.compose.material3.rememberDateRangePickerState +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.shadow +import androidx.compose.ui.unit.dp +import androidx.compose.ui.window.Popup +import java.text.SimpleDateFormat +import java.util.Date +import java.util.Locale + +// [START android_compose_components_datepicker_examples] +// [START_EXCLUDE] +@Composable +fun DatePickerExamples() { + var showModal by remember { mutableStateOf(false) } + var showModalInput by remember { mutableStateOf(false) } + var showRangeModal by remember { mutableStateOf(false) } +// [END_EXCLUDE] + var selectedDate by remember { mutableStateOf(null) } +// [START_EXCLUDE] + var selectedDateRange by remember { mutableStateOf>(null to null) } + + Column( + modifier = Modifier + .fillMaxSize() + .padding(16.dp), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.spacedBy(16.dp) + ) { + Text("Docked date picker:") + DatePickerDocked() + + Text("Modal date pickers:") + Button(onClick = { showModal = true }) { + Text("Show Modal Date Picker") + } + Button(onClick = { showModalInput = true }) { + Text("Show Modal Input Date Picker") + } +// [END_EXCLUDE] + if (selectedDate != null) { + val date = Date(selectedDate!!) + val formattedDate = SimpleDateFormat("MMM dd, yyyy", Locale.getDefault()).format(date) + Text("Selected date: $formattedDate") + } else { + Text("No date selected") + } +// [START_EXCLUDE] + + Text("Date range pickers:") + + Button(onClick = { showRangeModal = true }) { + Text("Show Modal Date Range Picker") + } + + if (selectedDateRange.first != null && selectedDateRange.second != null) { + val startDate = Date(selectedDateRange.first!!) + val endDate = Date(selectedDateRange.second!!) + val formattedStartDate = SimpleDateFormat("MMM dd, yyyy", Locale.getDefault()).format(startDate) + val formattedEndDate = SimpleDateFormat("MMM dd, yyyy", Locale.getDefault()).format(endDate) + Text("Selected date range: $formattedStartDate - $formattedEndDate") + } else { + Text("No date range selected") + } + } + + if (showModal) { +// [END_EXCLUDE] + DatePickerModal( + onDateSelected = { + selectedDate = it + showModal = false + }, + onDismiss = { showModal = false } + ) + } +// [START_EXCLUDE] + + if (showModalInput) { + DatePickerModalInput( + onDateSelected = { + selectedDate = it + showModalInput = false + }, + onDismiss = { showModalInput = false } + ) + } + + if (showRangeModal) { + DateRangePickerModal( + onDateRangeSelected = { + selectedDateRange = it + showRangeModal = false + }, + onDismiss = { showRangeModal = false } + ) + } +} +// [END android_compose_components_datepicker_examples] + +@OptIn(ExperimentalMaterial3Api::class) +// [START android_compose_components_datepicker_modal] +@Composable +fun DatePickerModal( + onDateSelected: (Long?) -> Unit, + onDismiss: () -> Unit +) { + val datePickerState = rememberDatePickerState() + + DatePickerDialog( + onDismissRequest = onDismiss, + confirmButton = { + TextButton(onClick = { + onDateSelected(datePickerState.selectedDateMillis) + onDismiss() + }) { + Text("OK") + } + }, + dismissButton = { + TextButton(onClick = onDismiss) { + Text("Cancel") + } + } + ) { + DatePicker(state = datePickerState) + } +} +// [END android_compose_components_datepicker_modal] + +@OptIn(ExperimentalMaterial3Api::class) +// [START android_compose_components_datepicker_inputmodal] +@Composable +fun DatePickerModalInput( + onDateSelected: (Long?) -> Unit, + onDismiss: () -> Unit +) { + val datePickerState = rememberDatePickerState(initialDisplayMode = DisplayMode.Input) + + DatePickerDialog( + onDismissRequest = onDismiss, + confirmButton = { + TextButton(onClick = { + onDateSelected(datePickerState.selectedDateMillis) + onDismiss() + }) { + Text("OK") + } + }, + dismissButton = { + TextButton(onClick = onDismiss) { + Text("Cancel") + } + } + ) { + DatePicker(state = datePickerState) + } +} +// [END android_compose_components_datepicker_inputmodal] + +@OptIn(ExperimentalMaterial3Api::class) +// [START android_compose_components_datepicker_docked] +@Composable +fun DatePickerDocked() { + var showDatePicker by remember { mutableStateOf(false) } + val datePickerState = rememberDatePickerState() + val selectedDate = datePickerState.selectedDateMillis?.let { + convertMillisToDate(it) + } ?: "" + + Box( + modifier = Modifier.fillMaxWidth() + ) { + OutlinedTextField( + value = selectedDate, + onValueChange = { }, + label = { Text("DOB") }, + readOnly = true, + trailingIcon = { + IconButton(onClick = { showDatePicker = !showDatePicker }) { + Icon( + imageVector = Icons.Default.DateRange, + contentDescription = "Select date" + ) + } + }, + modifier = Modifier + .fillMaxWidth() + .height(64.dp) + ) + + if (showDatePicker) { + Popup( + onDismissRequest = { showDatePicker = false }, + alignment = Alignment.TopStart + ) { + Box( + modifier = Modifier + .fillMaxWidth() + .offset(y = 64.dp) + .shadow(elevation = 4.dp) + .background(MaterialTheme.colorScheme.surface) + .padding(16.dp) + ) { + DatePicker( + state = datePickerState, + showModeToggle = false + ) + } + } + } + } +} + +fun convertMillisToDate(millis: Long): String { + val formatter = SimpleDateFormat("MM/dd/yyyy", Locale.getDefault()) + return formatter.format(Date(millis)) +} +// [END android_compose_components_datepicker_docked] + +@OptIn(ExperimentalMaterial3Api::class) +// [START android_compose_components_datepicker_range] +@Composable +fun DateRangePickerModal( + onDateRangeSelected: (Pair) -> Unit, + onDismiss: () -> Unit +) { + val dateRangePickerState = rememberDateRangePickerState() + + DatePickerDialog( + onDismissRequest = onDismiss, + confirmButton = { + TextButton( + onClick = { + onDateRangeSelected( + Pair( + dateRangePickerState.selectedStartDateMillis, + dateRangePickerState.selectedEndDateMillis + ) + ) + onDismiss() + } + ) { + Text("OK") + } + }, + dismissButton = { + TextButton(onClick = onDismiss) { + Text("Cancel") + } + } + ) { + DateRangePicker( + state = dateRangePickerState, + title = { + Text( + text = "Select date range" + ) + }, + showModeToggle = false, + modifier = Modifier + .fillMaxWidth() + .height(500.dp) + .padding(16.dp) + ) + } +} +// [END android_compose_components_datepicker_range] diff --git a/compose/snippets/src/main/java/com/example/compose/snippets/navigation/Destination.kt b/compose/snippets/src/main/java/com/example/compose/snippets/navigation/Destination.kt index 5aefdbcb3..9007ba4df 100644 --- a/compose/snippets/src/main/java/com/example/compose/snippets/navigation/Destination.kt +++ b/compose/snippets/src/main/java/com/example/compose/snippets/navigation/Destination.kt @@ -42,4 +42,5 @@ enum class TopComponentsDestination(val route: String, val title: String) { BadgeExamples("badgeExamples", "Badges"), PartialBottomSheet("partialBottomSheets", "Partial Bottom Sheet"), TimePickerExamples("timePickerExamples", "Time Pickers"), + DatePickerExamples("datePickerExamples", "Date Pickers"), } From 822ac2d63545f4ff40ee4e4b815bd13eb74c760d Mon Sep 17 00:00:00 2001 From: Chiara Chiappini Date: Wed, 7 Aug 2024 15:20:31 +0100 Subject: [PATCH 7/8] Break long instruction in 2 lines to optimize for DAC --- wear/src/main/java/com/example/wear/snippets/list/List.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/wear/src/main/java/com/example/wear/snippets/list/List.kt b/wear/src/main/java/com/example/wear/snippets/list/List.kt index 98cf8d187..962bee0ab 100644 --- a/wear/src/main/java/com/example/wear/snippets/list/List.kt +++ b/wear/src/main/java/com/example/wear/snippets/list/List.kt @@ -15,6 +15,7 @@ */ package com.example.wear.snippets.list + import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Build import androidx.compose.runtime.Composable @@ -107,7 +108,9 @@ fun SnapAndFlingComposeList() { const val LARGE_DISPLAY_BREAKPOINT = 225 @Composable -fun isLargeDisplay() = LocalConfiguration.current.screenWidthDp >= LARGE_DISPLAY_BREAKPOINT +fun isLargeDisplay() = + LocalConfiguration.current.screenWidthDp >= LARGE_DISPLAY_BREAKPOINT + // [START_EXCLUDE] @Composable fun breakpointDemo() { From 5ca7f540426f135a983c16cf481ba0878f00c465 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Mlynari=C4=8D?= Date: Thu, 8 Aug 2024 12:27:18 +0200 Subject: [PATCH 8/8] Prevent redrawing twice and running timer when compositions =0 (#304) --- .../compose/recomposehighlighter/RecomposeHighlighter.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/compose/recomposehighlighter/src/main/java/com/example/android/compose/recomposehighlighter/RecomposeHighlighter.kt b/compose/recomposehighlighter/src/main/java/com/example/android/compose/recomposehighlighter/RecomposeHighlighter.kt index 6638a7fa6..fdcbbda30 100644 --- a/compose/recomposehighlighter/src/main/java/com/example/android/compose/recomposehighlighter/RecomposeHighlighter.kt +++ b/compose/recomposehighlighter/src/main/java/com/example/android/compose/recomposehighlighter/RecomposeHighlighter.kt @@ -73,7 +73,7 @@ private class RecomposeHighlighterModifier : Modifier.Node(), DrawModifierNode { private var totalCompositions: Long = 0 set(value) { if (field == value) return - restartTimer() + if (value > 0) restartTimer() field = value invalidateDraw() } @@ -103,7 +103,6 @@ private class RecomposeHighlighterModifier : Modifier.Node(), DrawModifierNode { timerJob = coroutineScope.launch { delay(3000) totalCompositions = 0 - invalidateDraw() } }