compose-datetime-wheel-picker

repository·main·Indexed 42 days ago

https://github.com/darkokoa/compose-datetime-wheel-picker

A Compose Multiplatform library providing customizable wheel pickers for dates, times, and datetimes. It includes WheelDatePicker, WheelTimePicker, and WheelDateTimePicker components with support for internationalization, CJK-specific formatting, 12/24-hour time formats, and flexible visual customization via Modifiers.

Tokens
3K
Snippets
9
Records
15
Agent score
4%

What's inside compose-datetime-wheel-picker

  1. Understand the difference between onSnappedChanged and onSnapped

    main

    The pickers provide two types of callbacks for selection changes:

    1. onSnapped...Changed (e.g., onSnappedDateChanged): Invoked continuously while the user is scrolling. Each time a new item snaps into the selector, this is fired. Use this for live previews or syncing UI elements that need to react to in-flight values.

    2. onSnapped... (e.g., onSnappedDate): Invoked only once after the wheel comes to rest. This represents the user's final choice. Use this for committing the selection, such as saving to a database or navigating to a new screen.

  2. Control Picker Sizing with Modifiers

    main

    Since version 1.4.0, picker size is controlled exclusively via the Modifier.

    Intrinsic Defaults:

    • WheelDatePicker/WheelDateTimePicker: 256.dp width.
    • WheelTimePicker/WheelTextPicker: 128.dp width.
    • Height: Approximately 42.7.dp per row (e.g., rowCount = 3 results in ~128.dp height).

    Important Notes:

    • Increasing rowCount increases the total height of the picker rather than squeezing the rows.
    • Constraint Warning: The picker uses subcomposition for sizing and does not support intrinsic-measurement parents (e.g., IntrinsicSize.Min or Max). Always pass an explicit width or height via the modifier.
    // Fixed size
    WheelDatePicker(modifier = Modifier.size(300.dp, 160.dp)) { }
    
    // Fill width, fixed height
    WheelDatePicker(modifier = Modifier.fillMaxWidth().height(200.dp)) { }
    
    // Responsive width with height constraints
    WheelDatePicker(
      modifier = Modifier
        .widthIn(min = 240.dp, max = 400.dp)
        .heightIn(min = 128.dp),
    ) { }
  3. Install datetime-wheel-picker

    main

    To use the library, add Maven Central to your repositories and include the dependency in your project. You must also include kotlinx-datetime.

    Compose Multiplatform

    Add to your commonMain source set:

    kotlin {
      sourceSets {
        val commonMain by getting {
          dependencies {
            implementation("io.github.darkokoa:datetime-wheel-picker:<version>")
            implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.8.0")
          }
        }
      }
    }

    Android (Single-platform)

    Add to your dependencies block:

    dependencies {
      implementation("io.github.darkokoa:datetime-wheel-picker:<version>")
      implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.8.0")
    }

    Android API Level < 26

    If your minSdk is below 26, you must enable Desugaring:

    compileOptions {
      isCoreLibraryDesugaringEnabled = true
    }
    
    //... 
    
    dependencies {
      coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.1.5")
    }
    implementation("io.github.darkokoa:datetime-wheel-picker:<version>")
    implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.8.0")
  4. Use the Wheel Picker components

    main

    The library provides three main Composable pickers for Compose Multiplatform:

    • WheelDateTimePicker: A combined date and time picker.
    • WheelDatePicker: A date-only picker.
    • WheelTimePicker: A time-only picker.

    Each component takes a trailing lambda that provides the selected value (e.g., LocalDate, LocalTime, or LocalDateTime) when the wheel snaps to a value.

    // Date Picker
    WheelDatePicker { snappedDate -> 
        // Use snappedDate (LocalDate)
    }
    
    // Time Picker
    WheelTimePicker { snappedTime -> 
        // Use snappedTime (LocalTime)
    }
    
    // DateTime Picker
    WheelDateTimePicker { snappedDateTime -> 
        // Use snappedDateTime (LocalDateTime)
    }
  5. Migrate from `size: DpSize` to `Modifier.size`

    main

    In version 1.4.0, the size: DpSize parameter was removed. You must now use Modifier.size() to control dimensions.

    Old way (Pre-1.4.0):

    WheelDatePicker(size = DpSize(300.dp, 160.dp)) { }

    New way (1.4.0+):

    WheelDatePicker(modifier = Modifier.size(300.dp, 160.dp)) { }
  6. Create a Day-Month only picker

    main

    To create a picker that excludes the year (useful for birthdays or anniversaries), set yearsRange = null. This hides the year wheel entirely.

    WheelDatePicker(
      startDate = LocalDate(2025, 6, 15),
      yearsRange = null, // Hides the year picker
      dateFormatter = dateFormatter(
        dateOrder = DateOrder.DMY,
        monthDisplayStyle = MonthDisplayStyle.FULL
      )
    ) { snappedDate ->
      // Access snappedDate.month and snappedDate.dayOfMonth
    }
  7. Restrict the Year Range

    main

    You can limit the selectable years by providing an IntRange to the yearsRange parameter. This is useful for restricting selection to a specific window, such as the next 10 years or a birthdate range.

    // Only allow next 10 years
    WheelDatePicker(
      yearsRange = IntRange(2025, 2035),
      dateFormatter = dateFormatter(dateOrder = DateOrder.YMD)
    ) { snappedDate -> }
    
    // Only allow past 50 years
    val currentYear = Clock.System.now()
      .toLocalDateTime(TimeZone.currentSystemDefault()).year
    WheelDatePicker(
      yearsRange = IntRange(currentYear - 50, currentYear),
      dateFormatter = dateFormatter(dateOrder = DateOrder.DMY)
    ) { snappedDate -> }
  8. Style the selected item in pickers

    main

    You can style the centered (snapped) item differently from the inactive items using selectedTextStyle and selectedTextColor.

    Note that selectedTextColor overrides selectedTextStyle.color, similar to how Text(color = ...) works in Compose. In WheelTimePicker and WheelDateTimePicker, the colon separator follows these selected styles.

    WheelDatePicker(
      textStyle = MaterialTheme.typography.titleMedium,
      textColor = LocalContentColor.current,
      selectedTextStyle = MaterialTheme.typography.titleMedium.copy(fontWeight = FontWeight.Bold),
      selectedTextColor = MaterialTheme.colorScheme.primary,
    )
  9. Configure Date Field order and display

    main

    You can customize how dates are displayed using the dateFormatter function.

    Key options:

    • dateOrder: Set the sequence of fields using DateOrder.DMY (Day-Month-Year), DateOrder.MDY (Month-Day-Year), or DateOrder.YMD (Year-Month-Day).
    • monthDisplayStyle: Choose how months appear using MonthDisplayStyle.FULL, MonthDisplayStyle.SHORT, or MonthDisplayStyle.NUMERIC.

    Note: For non-Composable usage (e.g., when you only need to set the order), use the non-Composable dateFormatter() overload.

    WheelDatePicker(
      dateFormatter = dateFormatter(
        dateOrder = DateOrder.DMY,
        monthDisplayStyle = MonthDisplayStyle.FULL
      )
    ) { snappedDate -> }
  10. Configure WheelTimePicker

    main

    The WheelTimePicker component allows users to select a time via a wheel interface.

    Key Parameters:

    • startTime: Initial selected time (LocalTime). Defaults to LocalTime.now().
    • minTime: Minimum selectable time. Defaults to LocalTime.MIN.
    • maxTime: Maximum selectable time. Defaults to LocalTime.MAX.
    • timeFormatter: Controls 12/24 hour format.
    • onSnappedTimeChanged: Callback fired during scrolling for live updates.
    • onSnappedTime: Callback fired when scrolling settles on the final selection.

    TimeFormat Options:

    • TimeFormat.HOUR_24: 24-hour format (00:00 - 23:59).
    • TimeFormat.AM_PM: 12-hour format with AM/PM.
  11. Configure WheelDatePicker

    main

    The WheelDatePicker component allows users to select a date via a wheel interface.

    Key Parameters:

    • startDate: Initial selected date (LocalDate). Defaults to LocalDate.now().
    • minDate: Minimum selectable date. Defaults to LocalDate.EPOCH.
    • maxDate: Maximum selectable date. Defaults to LocalDate.CYB3R_1N1T_ZOLL.
    • yearsRange: IntRange? to display. Set to null to hide the year picker.
    • dateFormatter: Controls date order, month style, and CJK suffixes.
    • rowCount: Number of visible rows (default is 3).
    • onSnappedDateChanged: Callback fired during scrolling for live updates.
    • onSnappedDate: Callback fired when scrolling settles on the final selection.
  12. Configure WheelDateTimePicker

    main

    The WheelDateTimePicker combines date and time selection into a single wheel interface.

    Key Parameters:

    • startDateTime: Initial selected date-time (LocalDateTime). Defaults to LocalDateTime.now().
    • minDateTime: Minimum selectable date-time. Defaults to LocalDateTime.EPOCH.
    • maxDateTime: Maximum selectable date-time. Defaults to LocalDateTime.CYB3R_1N1T_ZOLL.
    • yearsRange: IntRange? to display. Set to null to hide the year picker.
    • dateFormatter: Controls date order, month style, and CJK suffixes.
    • timeFormatter: Controls 12/24 hour format.
    • onSnappedDateTimeChanged: Callback fired during scrolling for live updates.
    • onSnappedDateTime: Callback fired when scrolling settles on the final selection.