Skip to content

ListPreference

ListPreference is a preference row that opens a bottom sheet single-choice panel, mirroring ColorOS's COUIListPreference (COUIAlertDialog_BottomAssignment with coui_select_dialog_singlechoice rows). The row shows the selected entry as trailing assignment text plus the COUI popup indicator; the selected panel row ends with a primary-tinted check mark. Tapping an entry commits the selection and dismisses the panel.

MultiSelectListPreference is the multi-choice variant, mirroring COUIMultiSelectListPreference: panel rows end with a checkbox, and the selection is only committed when the confirm button is clicked.

Import

kotlin
import io.github.suqi8.coui.kmp.preference.ListPreference
import io.github.suqi8.coui.kmp.preference.ListPreferenceDefaults
import io.github.suqi8.coui.kmp.preference.ListPreferenceEntry
import io.github.suqi8.coui.kmp.preference.MultiSelectListPreference

Basic Usage

kotlin
val entries = remember {
    listOf(
        ListPreferenceEntry("Light"),
        ListPreferenceEntry("Dark"),
        ListPreferenceEntry("Follow system", summary = "Switch with the system dark mode"),
    )
}
var selectedIndex by remember { mutableIntStateOf(2) }

ListPreference(
    entries = entries,
    selectedIndex = selectedIndex,
    onSelectedIndexChange = { selectedIndex = it },
    title = "Theme",
    cancelButtonText = "Cancel",
)

Multi-choice Variant

kotlin
var selectedIndices by remember { mutableStateOf(setOf(0, 1)) }

MultiSelectListPreference(
    entries = entries,
    selectedIndices = selectedIndices,
    onSelectedIndicesChange = { selectedIndices = it },
    title = "Sync items",
    confirmButtonText = "Confirm",
    cancelButtonText = "Cancel",
)

Properties

ListPreferenceEntry

PropertyTypeDescriptionDefault ValueRequired
textStringEntry text (16sp, medium)-Yes
summaryString?Optional summary below the textnullNo
enabledBooleanWhether the entry can be selectedtrueNo

ListPreference

PropertyTypeDescriptionDefault ValueRequired
entriesList<ListPreferenceEntry>Entries to choose from-Yes
selectedIndexIntIndex of the selected entry (-1 = none)-Yes
onSelectedIndexChange(Int) -> UnitCallback when an entry is selected-Yes
titleStringTitle of the preference row-Yes
cancelButtonTextStringLabel of the panel cancel button-Yes
modifierModifierModifier applied to the rowModifierNo
titleColorBasicComponentColorsTitle color configurationBasicComponentDefaults.titleColor()No
summaryString?Summary of the preference rownullNo
summaryColorBasicComponentColorsSummary color configurationBasicComponentDefaults.summaryColor()No
dialogTitleStringTitle of the selection paneltitleNo
colorsListPreferenceColorsColors of the panel rowsListPreferenceDefaults.listPreferenceColors()No
startAction@Composable (() -> Unit)?Custom start side contentnullNo
bottomAction@Composable (() -> Unit)?Custom bottom contentnullNo
insideMarginPaddingValuesInternal content paddingBasicComponentDefaults.InsideMarginNo
cardListPositionCardListPositionRow position inside its card group; rounded outer edges gain extra paddingCardListPosition.NoneNo
enabledBooleanWhether the row is clickabletrueNo
showValueBooleanShow the selected entry as trailing texttrueNo
renderInRootScaffoldBooleanRender the panel in the root ScaffoldtrueNo
onExpandedChange((Boolean) -> Unit)?Callback when the panel is shown / dismissednullNo

MultiSelectListPreference

Additional / differing properties compared to ListPreference:

PropertyTypeDescriptionDefault ValueRequired
selectedIndicesSet<Int>Indices of the selected entries-Yes
onSelectedIndicesChange(Set<Int>) -> UnitCallback with the new selection on confirm-Yes
confirmButtonTextStringLabel of the panel confirm button-Yes
checkboxColorsCheckboxColorsColors of the panel row checkboxesCheckboxDefaults.checkboxColors()No

ListPreferenceDefaults

ConstantTypeDefault ValueCOUI source
PanelItemMinHeightDp48.dpcoui_delete_alert_dialog_button_height
PanelItemVerticalPaddingDp10.dpalert_dialog_single_list_padding_vertical
PanelItemIndicatorSpacingDp16.dpcoui_dialog_layout_margin_horizontal
PanelItemSummarySpacingDp2.dpcoui_alert_dialog_content_panel_padding_top
CheckIconSizeDp24.dpCOUI 24dp selection widgets
ButtonBarTopPaddingDp6.dpalert_dialog_single_list_last_item_padding_bottom
ButtonBarBottomPaddingDp12.dplibrary convention

listPreferenceColors() factory

ParameterTypeDefaultCOUI role
itemTextColorColorCOUITheme.colorScheme.onSurfacecouiColorPrimaryNeutral
disabledItemTextColorColorCOUITheme.colorScheme.disabledOnSecondaryVariantcouiColorDisabledNeutral
itemSummaryColorColorCOUITheme.colorScheme.onSurfaceSecondarycouiColorSecondNeutral
disabledItemSummaryColorColorCOUITheme.colorScheme.disabledOnSecondaryVariantcouiColorDisabledNeutral
selectedIndicatorColorColorCOUITheme.colorScheme.primarycouiColorPrimary
disabledSelectedIndicatorColorColorCOUITheme.colorScheme.disabledPrimary-

Behavior

  • Clicking the row opens an OverlayBottomSheet panel titled dialogTitle and keeps the row in the hold-down state until the panel is dismissed, with a context-click haptic on open.
  • Single choice: tapping an entry invokes onSelectedIndexChange and dismisses the panel immediately; the cancel button or an outside tap dismisses without changes (COUIListPreferenceDialogFragment).
  • Multi choice: toggling rows only updates a pending selection; the confirm button commits it via onSelectedIndicesChange, while cancel / outside tap discards it (COUIMultiSelectListPreferenceDialogFragment).
  • A hairline divider (0.33dp, couiColorDivider) is drawn between adjacent panel rows only, never after the last row.
  • Entries with enabled = false are shown but cannot be selected, using disabled text colors.

Changelog

Released under the Apache-2.0 License