Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 92324644 authored by Yuchen's avatar Yuchen
Browse files

[expressive design] Update SliderPreference.

Update layout of SliderPreference.
Enable icon to be on either left or right.

Test: visual
Bug: 360916599
Flag: EXEMPT bug fix
Change-Id: I5d9f22ab69b65919f40be00c13cc7417aeacb864
parent aad11054
Loading
Loading
Loading
Loading
+55 −42
Original line number Diff line number Diff line
@@ -33,10 +33,10 @@ import com.android.settingslib.spa.framework.common.SettingsPageProvider
import com.android.settingslib.spa.framework.common.createSettingsPage
import com.android.settingslib.spa.framework.compose.navigator
import com.android.settingslib.spa.framework.theme.SettingsTheme
import com.android.settingslib.spa.widget.preference.SliderPreference
import com.android.settingslib.spa.widget.preference.SliderPreferenceModel
import com.android.settingslib.spa.widget.preference.Preference
import com.android.settingslib.spa.widget.preference.PreferenceModel
import com.android.settingslib.spa.widget.preference.SliderPreference
import com.android.settingslib.spa.widget.preference.SliderPreferenceModel

private const val TITLE = "Sample Slider"

@@ -49,24 +49,30 @@ object SliderPageProvider : SettingsPageProvider {
        entryList.add(
            SettingsEntryBuilder.create("Simple Slider", owner)
                .setUiLayoutFn {
                    SliderPreference(object : SliderPreferenceModel {
                    SliderPreference(
                        object : SliderPreferenceModel {
                            override val title = "Simple Slider"
                            override val initValue = 40
                    })
                }.build()
                        }
                    )
                }
                .build()
        )
        entryList.add(
            SettingsEntryBuilder.create("Slider with icon", owner)
                .setUiLayoutFn {
                    SliderPreference(object : SliderPreferenceModel {
                    SliderPreference(
                        object : SliderPreferenceModel {
                            override val title = "Slider with icon"
                            override val initValue = 30
                            override val onValueChangeFinished = {
                                println("onValueChangeFinished")
                            }
                        override val icon = Icons.Outlined.AccessAlarm
                    })
                }.build()
                            override val iconStart = Icons.Outlined.AccessAlarm
                        }
                    )
                }
                .build()
        )
        entryList.add(
            SettingsEntryBuilder.create("Slider with changeable icon", owner)
@@ -74,42 +80,51 @@ object SliderPageProvider : SettingsPageProvider {
                    val initValue = 0
                    var icon by remember { mutableStateOf(Icons.Outlined.MusicOff) }
                    var sliderPosition by remember { mutableStateOf(initValue) }
                    SliderPreference(object : SliderPreferenceModel {
                    SliderPreference(
                        object : SliderPreferenceModel {
                            override val title = "Slider with changeable icon"
                            override val initValue = initValue
                            override val onValueChange = { it: Int ->
                                sliderPosition = it
                            icon = if (it > 0) Icons.Outlined.MusicNote else Icons.Outlined.MusicOff
                                icon =
                                    if (it > 0) Icons.Outlined.MusicNote
                                    else Icons.Outlined.MusicOff
                            }
                            override val onValueChangeFinished = {
                                println("onValueChangeFinished: the value is $sliderPosition")
                            }
                        override val icon = icon
                    })
                }.build()
                            override val iconEnd = icon
                        }
                    )
                }
                .build()
        )
        entryList.add(
            SettingsEntryBuilder.create("Slider with steps", owner)
                .setUiLayoutFn {
                    SliderPreference(object : SliderPreferenceModel {
                    SliderPreference(
                        object : SliderPreferenceModel {
                            override val title = "Slider with steps"
                            override val initValue = 2
                            override val valueRange = 1..5
                            override val showSteps = true
                    })
                }.build()
                        }
                    )
                }
                .build()
        )

        return entryList
    }

    fun buildInjectEntry(): SettingsEntryBuilder {
        return SettingsEntryBuilder.createInject(owner)
            .setUiLayoutFn {
                Preference(object : PreferenceModel {
        return SettingsEntryBuilder.createInject(owner).setUiLayoutFn {
            Preference(
                object : PreferenceModel {
                    override val title = TITLE
                    override val onClick = navigator(name)
                })
                }
            )
        }
    }

@@ -121,7 +136,5 @@ object SliderPageProvider : SettingsPageProvider {
@Preview(showBackground = true)
@Composable
private fun SliderPagePreview() {
    SettingsTheme {
        SliderPageProvider.Page(null)
    }
    SettingsTheme { SliderPageProvider.Page(null) }
}
+1 −1
Original line number Diff line number Diff line
@@ -60,7 +60,7 @@ class SliderPreferenceScreenshotTest(emulationSpec: DeviceEmulationSpec) {
                    override val onValueChangeFinished = {
                        println("onValueChangeFinished")
                    }
                    override val icon = Icons.Outlined.AccessAlarm
                    override val iconStart = Icons.Outlined.AccessAlarm
                })

                SliderPreference(object : SliderPreferenceModel {
+73 −37
Original line number Diff line number Diff line
@@ -16,6 +16,10 @@

package com.android.settingslib.spa.widget.preference

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.AccessAlarm
import androidx.compose.material.icons.outlined.MusicNote
@@ -27,30 +31,25 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.android.settingslib.spa.framework.theme.SettingsDimension
import com.android.settingslib.spa.framework.theme.SettingsTheme
import com.android.settingslib.spa.framework.util.EntryHighlight
import com.android.settingslib.spa.widget.ui.SettingsSlider

/**
 * The widget model for [SliderPreference] widget.
 */
/** The widget model for [SliderPreference] widget. */
interface SliderPreferenceModel {
    /**
     * The title of this [SliderPreference].
     */
    /** The title of this [SliderPreference]. */
    val title: String

    /**
     * The initial position of the [SliderPreference].
     */
    /** The initial position of the [SliderPreference]. */
    val initValue: Int

    /**
     * The value range for this [SliderPreference].
     */
    /** The value range for this [SliderPreference]. */
    val valueRange: IntRange
        get() = 0..100

@@ -69,15 +68,23 @@ interface SliderPreferenceModel {
        get() = null

    /**
     * The icon image for [SliderPreference]. If not specified, the slider hides the icon by default.
     * The start icon image for [SliderPreference]. If not specified, the slider hides the icon by
     * default.
     */
    val icon: ImageVector?
    val iconStart: ImageVector?
        get() = null

    /**
     * Indicates whether to show step marks. If show step marks, when user finish sliding,
     * the slider will automatically jump to the nearest step mark. Otherwise, the slider hides
     * the step marks by default.
     * The end icon image for [SliderPreference]. If not specified, the slider hides the icon by
     * default.
     */
    val iconEnd: ImageVector?
        get() = null

    /**
     * Indicates whether to show step marks. If show step marks, when user finish sliding, the
     * slider will automatically jump to the nearest step mark. Otherwise, the slider hides the step
     * marks by default.
     *
     * The step is fixed to 1.
     */
@@ -99,7 +106,8 @@ fun SliderPreference(model: SliderPreferenceModel) {
            valueRange = model.valueRange,
            onValueChange = model.onValueChange,
            onValueChangeFinished = model.onValueChangeFinished,
            icon = model.icon,
            iconStart = model.iconStart,
            iconEnd = model.iconEnd,
            showSteps = model.showSteps,
        )
    }
@@ -113,27 +121,45 @@ internal fun SliderPreference(
    valueRange: IntRange = 0..100,
    onValueChange: ((value: Int) -> Unit)? = null,
    onValueChangeFinished: (() -> Unit)? = null,
    icon: ImageVector? = null,
    iconStart: ImageVector? = null,
    iconEnd: ImageVector? = null,
    showSteps: Boolean = false,
) {

    BaseLayout(
        title = title,
        subTitle = {
            Row(verticalAlignment = Alignment.CenterVertically) {
                if (iconStart != null) {
                    SliderIcon(icon = iconStart)
                    Spacer(Modifier.padding(SettingsDimension.paddingSmall))
                }
                Box(Modifier.weight(1f)) {
                    SettingsSlider(
                        initValue,
                        modifier,
                        valueRange,
                        onValueChange,
                        onValueChangeFinished,
                showSteps
                        showSteps,
                    )
                }
                if (iconEnd != null) {
                    Spacer(Modifier.padding(SettingsDimension.paddingSmall))
                    SliderIcon(icon = iconEnd)
                }
            }
        },
        icon = if (icon != null) ({
            Icon(imageVector = icon, contentDescription = null)
        }) else null,
    )
}

@Composable
fun SliderIcon(icon: ImageVector) {
    Box(modifier = Modifier.padding(8.dp), contentAlignment = Alignment.Center) {
        Icon(imageVector = icon, contentDescription = null)
    }
}

@Preview
@Composable
private fun SliderPreferencePreview() {
@@ -147,7 +173,7 @@ private fun SliderPreferencePreview() {
            onValueChangeFinished = {
                println("onValueChangeFinished: the value is $sliderPosition")
            },
            icon = Icons.Outlined.AccessAlarm,
            iconStart = Icons.Outlined.AccessAlarm,
        )
    }
}
@@ -163,20 +189,30 @@ private fun SliderPreferenceIconChangePreview() {
            onValueChange = { it: Int ->
                icon = if (it > 0) Icons.Outlined.MusicNote else Icons.Outlined.MusicOff
            },
            icon = icon,
            iconEnd = icon,
        )
    }
}

@Preview
@Composable
private fun SliderPreferenceStepsPreview() {
private fun SliderPreferenceTwoIconPreview() {
    SettingsTheme {
        val iconStart by remember { mutableStateOf(Icons.Outlined.MusicNote) }
        val iconEnd by remember { mutableStateOf(Icons.Outlined.MusicOff) }
        SliderPreference(
            title = "Display Text",
            initValue = 2,
            valueRange = 1..5,
            showSteps = true,
            title = "Media Volume",
            initValue = 40,
            iconStart = iconStart,
            iconEnd = iconEnd,
        )
    }
}

@Preview
@Composable
private fun SliderPreferenceStepsPreview() {
    SettingsTheme {
        SliderPreference(title = "Display Text", initValue = 2, valueRange = 1..5, showSteps = true)
    }
}