New Compose Multiplatform components arrived on Composables UICheck it out →

PickerGroup

A group of [Picker]s to build components where multiple pickers are required to be combined together. The component maintains the focus between different [Picker]s by using [PickerGroupState]. It can be handled from outside the component using the same instance and its properties. When touch exploration services are enabled, the focus moves to the picker which is clicked. To handle clicks in a different manner, use the [onSelected] lambda to control the focus of talkback and actual focus.

It is recommended to ensure that a [Picker] in non read only mode should have user scroll enabled when touch exploration services are running.

Last updated:

Installation

dependencies {
   implementation("androidx.wear.compose:compose-material:1.4.0-beta03")
}

Overloads

@Composable
@OptIn(ExperimentalWearFoundationApi::class
fun PickerGroup(
    vararg pickers: PickerGroupItem,
    modifier: Modifier = Modifier,
    pickerGroupState: PickerGroupState = rememberPickerGroupState(),
    onSelected: (selectedIndex: Int) -> Unit = {},
    autoCenter: Boolean = true,
    propagateMinConstraints: Boolean = false,
    touchExplorationStateProvider: TouchExplorationStateProvider =
        DefaultTouchExplorationStateProvider(),
    separator: (@Composable (Int) -> Unit)? = null
)

Parameters

namedescription
pickersList of [Picker]s represented using [PickerGroupItem] in the same order of display from left to right.
modifierModifier to be applied to the PickerGroup
pickerGroupStateThe state of the component
onSelectedAction triggered when one of the [Picker] is selected inside the group
autoCenterIndicates whether the selected [Picker] should be centered on the screen. It is recommended to set this as true when all the pickers cannot be fit into the screen. Or provide a mechanism to navigate to pickers which are not visible on screen. If false, the whole row containing pickers would be centered.
propagateMinConstraintsWhether the incoming min constraints should be passed to content.
touchExplorationStateProviderA [TouchExplorationStateProvider] to provide the current state of touch exploration service. This will be used to determine how the PickerGroup and talkback focus behaves/reacts to click and scroll events.
separatorA composable block which describes the separator between different [Picker]s. The integer parameter to the composable depicts the index where it will be kept. For example, 0 would represent the separator between the first and second picker.

Code Examples

PickerGroup24Hours

@Composable
@Sampled
fun PickerGroup24Hours() {
    val pickerGroupState = rememberPickerGroupState()
    val pickerStateHour = rememberPickerState(initialNumberOfOptions = 24)
    val pickerStateMinute = rememberPickerState(initialNumberOfOptions = 60)
    Column(
        modifier = Modifier.fillMaxWidth(),
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        Spacer(modifier = Modifier.size(30.dp))
        Text(text = if (pickerGroupState.selectedIndex == 0) "Hours" else "Minutes")
        Spacer(modifier = Modifier.size(10.dp))
        PickerGroup(
            PickerGroupItem(
                pickerState = pickerStateHour,
                option = { optionIndex, _ -> Text(text = "%02d".format(optionIndex)) },
                modifier = Modifier.size(80.dp, 100.dp)
            ),
            PickerGroupItem(
                pickerState = pickerStateMinute,
                option = { optionIndex, _ -> Text(text = "%02d".format(optionIndex)) },
                modifier = Modifier.size(80.dp, 100.dp)
            ),
            pickerGroupState = pickerGroupState,
            autoCenter = false
        )
    }
}

AutoCenteringPickerGroup

@Composable
@Sampled
fun AutoCenteringPickerGroup() {
    val pickerGroupState = rememberPickerGroupState()
    val pickerStateHour = rememberPickerState(initialNumberOfOptions = 24)
    val pickerStateMinute = rememberPickerState(initialNumberOfOptions = 60)
    val pickerStateSeconds = rememberPickerState(initialNumberOfOptions = 60)
    val pickerStateMilliSeconds = rememberPickerState(initialNumberOfOptions = 1000)
    Column(
        modifier = Modifier.fillMaxWidth(),
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        val headingText = mapOf(
            0 to "Hours", 1 to "Minutes", 2 to "Seconds", 3 to "Milli"
        )
        Spacer(modifier = Modifier.size(30.dp))
        Text(text = headingText[pickerGroupState.selectedIndex]!!)
        Spacer(modifier = Modifier.size(10.dp))
        PickerGroup(
            PickerGroupItem(
                pickerState = pickerStateHour,
                option = { optionIndex, _ -> Text(text = "%02d".format(optionIndex)) },
                modifier = Modifier.size(80.dp, 100.dp)
            ),
            PickerGroupItem(
                pickerState = pickerStateMinute,
                option = { optionIndex, _ -> Text(text = "%02d".format(optionIndex)) },
                modifier = Modifier.size(80.dp, 100.dp)
            ),
            PickerGroupItem(
                pickerState = pickerStateSeconds,
                option = { optionIndex, _ -> Text(text = "%02d".format(optionIndex)) },
                modifier = Modifier.size(80.dp, 100.dp)
            ),
            PickerGroupItem(
                pickerState = pickerStateMilliSeconds,
                option = { optionIndex, _ -> Text(text = "%03d".format(optionIndex)) },
                modifier = Modifier.size(80.dp, 100.dp)
            ),
            pickerGroupState = pickerGroupState,
            autoCenter = true
        )
    }
}