Update switch style to match settings
This commit is contained in:
@@ -11,6 +11,7 @@ object ColorTokens {
|
||||
val Neutral1_50 = SwatchColorToken(Swatch.Neutral1, Shade.S50)
|
||||
val Neutral1_100 = SwatchColorToken(Swatch.Neutral1, Shade.S100)
|
||||
val Neutral1_200 = SwatchColorToken(Swatch.Neutral1, Shade.S200)
|
||||
val Neutral1_400 = SwatchColorToken(Swatch.Neutral1, Shade.S400)
|
||||
val Neutral1_500 = SwatchColorToken(Swatch.Neutral1, Shade.S500)
|
||||
val Neutral1_700 = SwatchColorToken(Swatch.Neutral1, Shade.S700)
|
||||
val Neutral1_800 = SwatchColorToken(Swatch.Neutral1, Shade.S800)
|
||||
@@ -33,6 +34,7 @@ object ColorTokens {
|
||||
|
||||
val Accent2_50 = SwatchColorToken(Swatch.Accent2, Shade.S50)
|
||||
val Accent2_100 = SwatchColorToken(Swatch.Accent2, Shade.S100)
|
||||
val Accent2_500 = SwatchColorToken(Swatch.Accent2, Shade.S500)
|
||||
val Accent2_600 = SwatchColorToken(Swatch.Accent2, Shade.S600)
|
||||
|
||||
val Accent3_50 = SwatchColorToken(Swatch.Accent3, Shade.S50)
|
||||
@@ -86,6 +88,13 @@ object ColorTokens {
|
||||
@JvmField val WidgetsPickerScrim = DayNightColorToken(Neutral1_200, Neutral1_900).setAlpha(0.8f)
|
||||
|
||||
@JvmField val WorkspaceAccentColor = DarkTextColorToken(Accent1_100, Accent2_600)
|
||||
|
||||
val SwitchThumbOn = Accent1_100
|
||||
val SwitchThumbOff = DayNightColorToken(Neutral2_300, Neutral1_400)
|
||||
val SwitchThumbDisabled = DayNightColorToken(Neutral2_100, Neutral1_700)
|
||||
|
||||
val SwitchTrackOn = DayNightColorToken(Accent1_600, Accent2_500.setLStar(51.0))
|
||||
val SwitchTrackOff = DayNightColorToken(Neutral2_500.setLStar(45.0), Neutral1_700)
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright 2021 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
|
||||
*
|
||||
* http://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 app.lawnchair.ui
|
||||
|
||||
import androidx.compose.material.ExperimentalMaterialApi
|
||||
import androidx.compose.runtime.ProvidableCompositionLocal
|
||||
import androidx.compose.runtime.staticCompositionLocalOf
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.composed
|
||||
import androidx.compose.ui.layout.LayoutModifier
|
||||
import androidx.compose.ui.layout.Measurable
|
||||
import androidx.compose.ui.layout.MeasureResult
|
||||
import androidx.compose.ui.layout.MeasureScope
|
||||
import androidx.compose.ui.platform.LocalViewConfiguration
|
||||
import androidx.compose.ui.platform.debugInspectorInfo
|
||||
import androidx.compose.ui.unit.Constraints
|
||||
import androidx.compose.ui.unit.DpSize
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
@OptIn(ExperimentalMaterialApi::class)
|
||||
@Suppress("ModifierInspectorInfo")
|
||||
internal fun Modifier.minimumTouchTargetSize(): Modifier = composed(
|
||||
inspectorInfo = debugInspectorInfo {
|
||||
name = "minimumTouchTargetSize"
|
||||
// TODO: b/214589635 - surface this information through the layout inspector in a better way
|
||||
// - for now just add some information to help developers debug what this size represents.
|
||||
properties["README"] = "Adds outer padding to measure at least 48.dp (default) in " +
|
||||
"size to disambiguate touch interactions if the element would measure smaller"
|
||||
}
|
||||
) {
|
||||
if (LocalMinimumTouchTargetEnforcement.current) {
|
||||
// TODO: consider using a hardcoded value of 48.dp instead to avoid inconsistent UI if the
|
||||
// LocalViewConfiguration changes across devices / during runtime.
|
||||
val size = LocalViewConfiguration.current.minimumTouchTargetSize
|
||||
MinimumTouchTargetModifier(size)
|
||||
} else {
|
||||
Modifier
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* CompositionLocal that configures whether Material components that have a visual size that is
|
||||
* lower than the minimum touch target size for accessibility (such as [Button]) will include
|
||||
* extra space outside the component to ensure that they are accessible. If set to false there
|
||||
* will be no extra space, and so it is possible that if the component is placed near the edge of
|
||||
* a layout / near to another component without any padding, there will not be enough space for
|
||||
* an accessible touch target.
|
||||
*/
|
||||
@Suppress("OPT_IN_MARKER_ON_WRONG_TARGET")
|
||||
@ExperimentalMaterialApi
|
||||
val LocalMinimumTouchTargetEnforcement: ProvidableCompositionLocal<Boolean> =
|
||||
staticCompositionLocalOf { true }
|
||||
|
||||
private class MinimumTouchTargetModifier(val size: DpSize) : LayoutModifier {
|
||||
override fun MeasureScope.measure(
|
||||
measurable: Measurable,
|
||||
constraints: Constraints
|
||||
): MeasureResult {
|
||||
|
||||
val placeable = measurable.measure(constraints)
|
||||
|
||||
// Be at least as big as the minimum dimension in both dimensions
|
||||
val width = maxOf(placeable.width, size.width.roundToPx())
|
||||
val height = maxOf(placeable.height, size.height.roundToPx())
|
||||
|
||||
return layout(width, height) {
|
||||
val centerX = ((width - placeable.width) / 2f).roundToInt()
|
||||
val centerY = ((height - placeable.height) / 2f).roundToInt()
|
||||
placeable.place(centerX, centerY)
|
||||
}
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
val otherModifier = other as? MinimumTouchTargetModifier ?: return false
|
||||
return size == otherModifier.size
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return size.hashCode()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,372 @@
|
||||
/*
|
||||
* Copyright 2018 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
|
||||
*
|
||||
* http://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 app.lawnchair.ui.preferences.components
|
||||
|
||||
import androidx.compose.animation.core.AnimationSpec
|
||||
import androidx.compose.animation.core.TweenSpec
|
||||
import androidx.compose.foundation.Canvas
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.gestures.Orientation
|
||||
import androidx.compose.foundation.indication
|
||||
import androidx.compose.foundation.interaction.DragInteraction
|
||||
import androidx.compose.foundation.interaction.Interaction
|
||||
import androidx.compose.foundation.interaction.InteractionSource
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.interaction.PressInteraction
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.BoxScope
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.offset
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.requiredSize
|
||||
import androidx.compose.foundation.layout.wrapContentSize
|
||||
import androidx.compose.foundation.selection.toggleable
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.material.*
|
||||
import androidx.compose.material.ripple.rememberRipple
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.geometry.Offset
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.StrokeCap
|
||||
import androidx.compose.ui.graphics.drawscope.DrawScope
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.platform.LocalLayoutDirection
|
||||
import androidx.compose.ui.semantics.Role
|
||||
import androidx.compose.ui.unit.IntOffset
|
||||
import androidx.compose.ui.unit.LayoutDirection
|
||||
import androidx.compose.ui.unit.dp
|
||||
import app.lawnchair.theme.UiColorMode
|
||||
import app.lawnchair.theme.color.ColorTokens
|
||||
import app.lawnchair.ui.minimumTouchTargetSize
|
||||
import dev.kdrag0n.monet.theme.toComposeColor
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
/**
|
||||
* <a href="https://material.io/components/switches" class="external" target="_blank">Material Design switch</a>.
|
||||
*
|
||||
* Switches toggle the state of a single item on or off.
|
||||
*
|
||||
* 
|
||||
*
|
||||
* @param checked whether or not this component is checked
|
||||
* @param onCheckedChange callback to be invoked when Switch is being clicked,
|
||||
* therefore the change of checked state is requested. If null, then this is passive
|
||||
* and relies entirely on a higher-level component to control the "checked" state.
|
||||
* @param modifier Modifier to be applied to the switch layout
|
||||
* @param enabled whether the component is enabled or grayed out
|
||||
* @param interactionSource the [MutableInteractionSource] representing the stream of
|
||||
* [Interaction]s for this Switch. You can create and pass in your own remembered
|
||||
* [MutableInteractionSource] if you want to observe [Interaction]s and customize the
|
||||
* appearance / behavior of this Switch in different [Interaction]s.
|
||||
* @param colors [SwitchColors] that will be used to determine the color of the thumb and track
|
||||
* in different states. See [SwitchDefaults.colors].
|
||||
*/
|
||||
@Composable
|
||||
@OptIn(ExperimentalMaterialApi::class)
|
||||
fun MYSwitch(
|
||||
checked: Boolean,
|
||||
onCheckedChange: ((Boolean) -> Unit)?,
|
||||
modifier: Modifier = Modifier,
|
||||
enabled: Boolean = true,
|
||||
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
|
||||
colors: SwitchColors = SwitchDefaults.colors()
|
||||
) {
|
||||
val minBound = with(LocalDensity.current) { ThumbInset.toPx() }
|
||||
val maxBound = with(LocalDensity.current) { (ThumbPathLength - ThumbInset).toPx() }
|
||||
val swipeableState = rememberSwipeableStateFor(checked, onCheckedChange ?: {}, AnimationSpec)
|
||||
val isRtl = LocalLayoutDirection.current == LayoutDirection.Rtl
|
||||
val toggleableModifier =
|
||||
if (onCheckedChange != null) {
|
||||
Modifier.toggleable(
|
||||
value = checked,
|
||||
onValueChange = onCheckedChange,
|
||||
enabled = enabled,
|
||||
role = Role.Switch,
|
||||
interactionSource = interactionSource,
|
||||
indication = null
|
||||
)
|
||||
} else {
|
||||
Modifier
|
||||
}
|
||||
|
||||
Box(
|
||||
modifier
|
||||
.then(
|
||||
if (onCheckedChange != null) Modifier.minimumTouchTargetSize() else Modifier
|
||||
)
|
||||
.then(toggleableModifier)
|
||||
.swipeable(
|
||||
state = swipeableState,
|
||||
anchors = mapOf(minBound to false, maxBound to true),
|
||||
thresholds = { _, _ -> FractionalThreshold(0.5f) },
|
||||
orientation = Orientation.Horizontal,
|
||||
enabled = enabled && onCheckedChange != null,
|
||||
reverseDirection = isRtl,
|
||||
interactionSource = interactionSource,
|
||||
resistance = null
|
||||
)
|
||||
.wrapContentSize(Alignment.Center)
|
||||
.padding(DefaultSwitchPadding)
|
||||
.requiredSize(SwitchWidth, SwitchHeight)
|
||||
) {
|
||||
MYSwitchImpl(
|
||||
checked = checked,
|
||||
enabled = enabled,
|
||||
colors = colors,
|
||||
thumbValue = swipeableState.offset,
|
||||
interactionSource = interactionSource
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the colors used by a [Switch] in different states
|
||||
*
|
||||
* See [SwitchDefaults.colors] for the default implementation that follows Material
|
||||
* specifications.
|
||||
*/
|
||||
@Stable
|
||||
interface SwitchColors {
|
||||
|
||||
/**
|
||||
* Represents the color used for the switch's thumb, depending on [enabled] and [checked].
|
||||
*
|
||||
* @param enabled whether the [Switch] is enabled or not
|
||||
* @param checked whether the [Switch] is checked or not
|
||||
*/
|
||||
@Composable
|
||||
fun thumbColor(enabled: Boolean, checked: Boolean): State<Color>
|
||||
|
||||
/**
|
||||
* Represents the color used for the switch's track, depending on [enabled] and [checked].
|
||||
*
|
||||
* @param enabled whether the [Switch] is enabled or not
|
||||
* @param checked whether the [Switch] is checked or not
|
||||
*/
|
||||
@Composable
|
||||
fun trackColor(enabled: Boolean, checked: Boolean): State<Color>
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun BoxScope.MYSwitchImpl(
|
||||
checked: Boolean,
|
||||
enabled: Boolean,
|
||||
colors: SwitchColors,
|
||||
thumbValue: State<Float>,
|
||||
interactionSource: InteractionSource
|
||||
) {
|
||||
val interactions = remember { mutableStateListOf<Interaction>() }
|
||||
|
||||
LaunchedEffect(interactionSource) {
|
||||
interactionSource.interactions.collect { interaction ->
|
||||
when (interaction) {
|
||||
is PressInteraction.Press -> interactions.add(interaction)
|
||||
is PressInteraction.Release -> interactions.remove(interaction.press)
|
||||
is PressInteraction.Cancel -> interactions.remove(interaction.press)
|
||||
is DragInteraction.Start -> interactions.add(interaction)
|
||||
is DragInteraction.Stop -> interactions.remove(interaction.start)
|
||||
is DragInteraction.Cancel -> interactions.remove(interaction.start)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val trackColor by colors.trackColor(enabled, checked)
|
||||
Canvas(Modifier.align(Alignment.Center).fillMaxSize()) {
|
||||
drawTrack(trackColor, TrackWidth.toPx(), TrackStrokeWidth.toPx())
|
||||
}
|
||||
val thumbColor by colors.thumbColor(enabled, checked)
|
||||
Spacer(
|
||||
Modifier
|
||||
.align(Alignment.CenterStart)
|
||||
.offset { IntOffset(thumbValue.value.roundToInt(), 0) }
|
||||
.indication(
|
||||
interactionSource = interactionSource,
|
||||
indication = rememberRipple(bounded = false, radius = ThumbRippleRadius)
|
||||
)
|
||||
.requiredSize(ThumbDiameter)
|
||||
.background(thumbColor, CircleShape)
|
||||
)
|
||||
}
|
||||
|
||||
private fun DrawScope.drawTrack(trackColor: Color, trackWidth: Float, strokeWidth: Float) {
|
||||
val strokeRadius = strokeWidth / 2
|
||||
drawLine(
|
||||
trackColor,
|
||||
Offset(strokeRadius, center.y),
|
||||
Offset(trackWidth - strokeRadius, center.y),
|
||||
strokeWidth,
|
||||
StrokeCap.Round
|
||||
)
|
||||
}
|
||||
|
||||
internal val TrackWidth = 52.dp
|
||||
internal val TrackStrokeWidth = 28.dp
|
||||
internal val ThumbDiameter = 20.dp
|
||||
|
||||
private val ThumbRippleRadius = 24.dp
|
||||
|
||||
private val DefaultSwitchPadding = 2.dp
|
||||
private val SwitchWidth = TrackWidth
|
||||
private val SwitchHeight = ThumbDiameter
|
||||
private val ThumbInset = 4.dp
|
||||
private val ThumbPathLength = TrackWidth - ThumbDiameter
|
||||
|
||||
private val AnimationSpec = TweenSpec<Float>(durationMillis = 100)
|
||||
|
||||
/**
|
||||
* Contains the default values used by [Switch]
|
||||
*/
|
||||
object SwitchDefaults {
|
||||
/**
|
||||
* Creates a [SwitchColors] that represents the different colors used in a [Switch] in
|
||||
* different states.
|
||||
*/
|
||||
@Composable
|
||||
fun colors(): SwitchColors {
|
||||
val context = LocalContext.current
|
||||
val isLightTheme = MaterialTheme.colors.isLight
|
||||
val colorMode = if (isLightTheme) UiColorMode.Light else UiColorMode.Dark
|
||||
|
||||
val thumbOn = ColorTokens.SwitchThumbOn.resolve(context, colorMode).toComposeColor()
|
||||
val thumbOff = ColorTokens.SwitchThumbOff.resolve(context, colorMode).toComposeColor()
|
||||
val thumbDisabled = ColorTokens.SwitchThumbDisabled.resolve(context, colorMode).toComposeColor()
|
||||
|
||||
val trackOn = ColorTokens.SwitchTrackOn.resolve(context, colorMode).toComposeColor()
|
||||
val trackOff = ColorTokens.SwitchTrackOff.resolve(context, colorMode).toComposeColor()
|
||||
val trackDisabled = trackOff.copy(alpha = ContentAlpha.disabled)
|
||||
|
||||
return DefaultSwitchColors(
|
||||
checkedThumbColor = thumbOn,
|
||||
checkedTrackColor = trackOn,
|
||||
uncheckedThumbColor = thumbOff,
|
||||
uncheckedTrackColor = trackOff,
|
||||
disabledCheckedThumbColor = thumbDisabled,
|
||||
disabledCheckedTrackColor = trackDisabled,
|
||||
disabledUncheckedThumbColor = thumbDisabled,
|
||||
disabledUncheckedTrackColor = trackDisabled
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Default [SwitchColors] implementation.
|
||||
*/
|
||||
@Immutable
|
||||
private class DefaultSwitchColors(
|
||||
private val checkedThumbColor: Color,
|
||||
private val checkedTrackColor: Color,
|
||||
private val uncheckedThumbColor: Color,
|
||||
private val uncheckedTrackColor: Color,
|
||||
private val disabledCheckedThumbColor: Color,
|
||||
private val disabledCheckedTrackColor: Color,
|
||||
private val disabledUncheckedThumbColor: Color,
|
||||
private val disabledUncheckedTrackColor: Color
|
||||
) : SwitchColors {
|
||||
@Composable
|
||||
override fun thumbColor(enabled: Boolean, checked: Boolean): State<Color> {
|
||||
return rememberUpdatedState(
|
||||
if (enabled) {
|
||||
if (checked) checkedThumbColor else uncheckedThumbColor
|
||||
} else {
|
||||
if (checked) disabledCheckedThumbColor else disabledUncheckedThumbColor
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
override fun trackColor(enabled: Boolean, checked: Boolean): State<Color> {
|
||||
return rememberUpdatedState(
|
||||
if (enabled) {
|
||||
if (checked) checkedTrackColor else uncheckedTrackColor
|
||||
} else {
|
||||
if (checked) disabledCheckedTrackColor else disabledUncheckedTrackColor
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (other == null || this::class != other::class) return false
|
||||
|
||||
other as DefaultSwitchColors
|
||||
|
||||
if (checkedThumbColor != other.checkedThumbColor) return false
|
||||
if (checkedTrackColor != other.checkedTrackColor) return false
|
||||
if (uncheckedThumbColor != other.uncheckedThumbColor) return false
|
||||
if (uncheckedTrackColor != other.uncheckedTrackColor) return false
|
||||
if (disabledCheckedThumbColor != other.disabledCheckedThumbColor) return false
|
||||
if (disabledCheckedTrackColor != other.disabledCheckedTrackColor) return false
|
||||
if (disabledUncheckedThumbColor != other.disabledUncheckedThumbColor) return false
|
||||
if (disabledUncheckedTrackColor != other.disabledUncheckedTrackColor) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = checkedThumbColor.hashCode()
|
||||
result = 31 * result + checkedTrackColor.hashCode()
|
||||
result = 31 * result + uncheckedThumbColor.hashCode()
|
||||
result = 31 * result + uncheckedTrackColor.hashCode()
|
||||
result = 31 * result + disabledCheckedThumbColor.hashCode()
|
||||
result = 31 * result + disabledCheckedTrackColor.hashCode()
|
||||
result = 31 * result + disabledUncheckedThumbColor.hashCode()
|
||||
result = 31 * result + disabledUncheckedTrackColor.hashCode()
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and [remember] a [SwipeableState] which is kept in sync with another state, i.e.:
|
||||
* 1. Whenever the [value] changes, the [SwipeableState] will be animated to that new value.
|
||||
* 2. Whenever the value of the [SwipeableState] changes (e.g. after a swipe), the owner of the
|
||||
* [value] will be notified to update their state to the new value of the [SwipeableState] by
|
||||
* invoking [onValueChange]. If the owner does not update their state to the provided value for
|
||||
* some reason, then the [SwipeableState] will perform a rollback to the previous, correct value.
|
||||
*/
|
||||
@Composable
|
||||
@ExperimentalMaterialApi
|
||||
internal fun <T : Any> rememberSwipeableStateFor(
|
||||
value: T,
|
||||
onValueChange: (T) -> Unit,
|
||||
animationSpec: AnimationSpec<Float> = SwipeableDefaults.AnimationSpec
|
||||
): SwipeableState<T> {
|
||||
val swipeableState = remember {
|
||||
SwipeableState(
|
||||
initialValue = value,
|
||||
animationSpec = animationSpec,
|
||||
confirmStateChange = { true }
|
||||
)
|
||||
}
|
||||
val forceAnimationCheck = remember { mutableStateOf(false) }
|
||||
LaunchedEffect(value, forceAnimationCheck.value) {
|
||||
if (value != swipeableState.currentValue) {
|
||||
swipeableState.animateTo(value)
|
||||
}
|
||||
}
|
||||
DisposableEffect(swipeableState.currentValue) {
|
||||
if (value != swipeableState.currentValue) {
|
||||
onValueChange(swipeableState.currentValue)
|
||||
forceAnimationCheck.value = !forceAnimationCheck.value
|
||||
}
|
||||
onDispose { }
|
||||
}
|
||||
return swipeableState
|
||||
}
|
||||
@@ -18,8 +18,6 @@ package app.lawnchair.ui.preferences.components
|
||||
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.material.Switch
|
||||
import androidx.compose.material.SwitchDefaults
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
@@ -59,13 +57,12 @@ fun SwitchPreference(
|
||||
title = { Text(text = label) },
|
||||
description = { description?.let { Text(text = it) } },
|
||||
endWidget = {
|
||||
Switch(
|
||||
MYSwitch(
|
||||
modifier = Modifier
|
||||
.height(24.dp),
|
||||
checked = checked,
|
||||
onCheckedChange = onCheckedChange,
|
||||
enabled = enabled,
|
||||
colors = SwitchDefaults.colors(checkedThumbColor = MaterialTheme.colorScheme.primary),
|
||||
)
|
||||
},
|
||||
modifier = Modifier
|
||||
|
||||
@@ -33,4 +33,4 @@ abstract class ColorScheme {
|
||||
get() = listOf(accent1, accent2, accent3)
|
||||
}
|
||||
|
||||
private fun Color.toComposeColor() = ComposeColor(toAndroidColor())
|
||||
fun Color.toComposeColor() = ComposeColor(toAndroidColor())
|
||||
|
||||
Reference in New Issue
Block a user