/*
* Copyright 2019 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.
*/
@file:Suppress("NOTHING_TO_INLINE")
package androidx.compose.material
import androidx.compose.animation.AnimatedValueModel
import androidx.compose.animation.asDisposableClock
import androidx.compose.animation.core.AnimationClockObservable
import androidx.compose.animation.core.AnimationVector1D
import androidx.compose.animation.core.VectorConverter
import androidx.compose.foundation.AmbientIndication
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.Interaction
import androidx.compose.foundation.InteractionState
import androidx.compose.foundation.clickable
import androidx.compose.foundation.indication
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.defaultMinSizeConstraints
import androidx.compose.foundation.layout.padding
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Immutable
import androidx.compose.runtime.Providers
import androidx.compose.runtime.Stable
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.graphics.compositeOver
import androidx.compose.ui.platform.AmbientAnimationClock
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
/**
* Material Design implementation of a
* [Material Contained Button](https://material.io/design/components/buttons.html#contained-button).
*
* Contained buttons are high-emphasis, distinguished by their use of elevation and fill. They
* contain actions that are primary to your app.
*
* To make a button clickable, you must provide an onClick. If no onClick is provided, this button
* will display itself as disabled.
*
* The default text style for internal [Text] components will be set to [Typography.button]. Text
* color will try to match the correlated color for the background color. For example if the
* background color is set to [Colors.primary] then the text will by default use
* [Colors.onPrimary].
*
* @sample androidx.compose.material.samples.ButtonSample
*
* If you need to add an icon just put it inside the [content] slot together with a spacing
* and a text:
*
* @sample androidx.compose.material.samples.ButtonWithIconSample
*
* @param onClick Will be called when the user clicks the button
* @param modifier Modifier to be applied to the button
* @param enabled Controls the enabled state of the button. When `false`, this button will not
* be clickable
* @param interactionState the [InteractionState] representing the different [Interaction]s
* present on this Button. You can create and pass in your own remembered [InteractionState] if
* you want to read the [InteractionState] and customize the appearance / behavior of this Button
* in different [Interaction]s, such as customizing how the [elevation] of this Button changes when
* it is [Interaction.Pressed].
* @param elevation [ButtonElevation] used to resolve the elevation for this button in different
* states. This controls the size of the shadow below the button. Pass `null` here to disable
* elevation for this button. See [ButtonDefaults.elevation].
* @param shape Defines the button's shape as well as its shadow
* @param border Border to draw around the button
* @param colors [ButtonColors] that will be used to resolve the background and content color for
* this button in different states. See [ButtonDefaults.buttonColors].
* @param contentPadding The spacing values to apply internally between the container and the content
*/
@OptIn(ExperimentalMaterialApi::class)
@Composable
fun Button(
onClick: () -> Unit,
modifier: Modifier = Modifier,
enabled: Boolean = true,
interactionState: InteractionState = remember { InteractionState() },
elevation: ButtonElevation? = ButtonDefaults.elevation(),
shape: Shape = MaterialTheme.shapes.small,
border: BorderStroke? = null,
colors: ButtonColors = ButtonDefaults.buttonColors(),
contentPadding: PaddingValues = ButtonDefaults.ContentPadding,
content: @Composable RowScope.() -> Unit
) {
// TODO(aelias): Avoid manually putting the clickable above the clip and
// the ripple below the clip once http://b/157687898 is fixed and we have
// more flexibility to move the clickable modifier (see candidate approach
// aosp/1361921)
val contentColor = colors.contentColor(enabled)
Surface(
shape = shape,
color = colors.backgroundColor(enabled),
contentColor = contentColor.copy(alpha = 1f),
border = border,
elevation = elevation?.elevation(enabled, interactionState) ?: 0.dp,
modifier = modifier.clickable(
onClick = onClick,
enabled = enabled,
interactionState = interactionState,
indication = null
)
) {
Providers(AmbientContentAlpha provides contentColor.alpha) {
ProvideTextStyle(
value = MaterialTheme.typography.button
) {
Row(
Modifier
.defaultMinSizeConstraints(
minWidth = ButtonDefaults.MinWidth,
minHeight = ButtonDefaults.MinHeight
)
.indication(interactionState, AmbientIndication.current())
.padding(contentPadding),
horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically,
content = content
)
}
}
}
}
/**
* Material Design implementation of a
* [Material Outlined Button](https://material.io/design/components/buttons.html#outlined-button).
*
* Outlined buttons are medium-emphasis buttons. They contain actions that are important, but are
* not the primary action in an app.
*
* Outlined buttons are also a lower emphasis alternative to contained buttons, or a higher emphasis
* alternative to text buttons.
*
* To make a button clickable, you must provide an onClick. If no onClick is provided, this button
* will display itself as disabled.
*
* The default text style for internal [Text] components will be set to [Typography.button]. Text
* color will try to match the correlated color for the background color. For example if the
* background color is set to [Colors.primary] then the text will by default use
* [Colors.onPrimary].
*
* @sample androidx.compose.material.samples.OutlinedButtonSample
*
* @param onClick Will be called when the user clicks the button
* @param modifier Modifier to be applied to the button
* @param enabled Controls the enabled state of the button. When `false`, this button will not
* be clickable
* @param interactionState the [InteractionState] representing the different [Interaction]s
* present on this Button. You can create and pass in your own remembered [InteractionState] if
* you want to read the [InteractionState] and customize the appearance / behavior of this Button
* in different [Interaction]s, such as customizing how the [elevation] of this Button changes when
* it is [Interaction.Pressed].
* @param elevation [ButtonElevation] used to resolve the elevation for this button in different
* states. An OutlinedButton typically has no elevation, see [Button] for a button with elevation.
* @param shape Defines the button's shape as well as its shadow
* @param border Border to draw around the button
* @param colors [ButtonColors] that will be used to resolve the background and content color for
* this button in different states. See [ButtonDefaults.outlinedButtonColors].
* @param contentPadding The spacing values to apply internally between the container and the content
*/
@OptIn(ExperimentalMaterialApi::class)
@Composable
inline fun OutlinedButton(
noinline onClick: () -> Unit,
modifier: Modifier = Modifier,
enabled: Boolean = true,
interactionState: InteractionState = remember { InteractionState() },
elevation: ButtonElevation? = null,
shape: Shape = MaterialTheme.shapes.small,
border: BorderStroke? = ButtonDefaults.outlinedBorder,
colors: ButtonColors = ButtonDefaults.outlinedButtonColors(),
contentPadding: PaddingValues = ButtonDefaults.ContentPadding,
noinline content: @Composable RowScope.() -> Unit
) = Button(
onClick = onClick,
modifier = modifier,
enabled = enabled,
interactionState = interactionState,
elevation = elevation,
shape = shape,
border = border,
colors = colors,
contentPadding = contentPadding,
content = content
)
/**
* Material Design implementation of a
* [Material Text Button](https://material.io/design/components/buttons.html#text-button).
*
* Text buttons are typically used for less-pronounced actions, including those located in cards and
* dialogs.
*
* To make a button clickable, you must provide an onClick. If no onClick is provided, this button
* will display itself as disabled.
*
* The default text style for internal [Text] components will be set to [Typography.button]. Text
* color will try to match the correlated color for the background color. For example if the
* background color is set to [Colors.primary] then the text will by default use
* [Colors.onPrimary].
*
* @sample androidx.compose.material.samples.TextButtonSample
*
* @param onClick Will be called when the user clicks the button
* @param modifier Modifier to be applied to the button
* @param enabled Controls the enabled state of the button. When `false`, this button will not
* be clickable
* @param interactionState the [InteractionState] representing the different [Interaction]s
* present on this Button. You can create and pass in your own remembered [InteractionState] if
* you want to read the [InteractionState] and customize the appearance / behavior of this Button
* in different [Interaction]s, such as customizing how the [elevation] of this Button changes when
* it is [Interaction.Pressed].
* @param elevation [ButtonElevation] used to resolve the elevation for this button in different
* states. A TextButton typically has no elevation, see [Button] for a button with elevation.
* @param shape Defines the button's shape as well as its shadow
* @param border Border to draw around the button
* @param colors [ButtonColors] that will be used to resolve the background and content color for
* this button in different states. See [ButtonDefaults.textButtonColors].
* @param contentPadding The spacing values to apply internally between the container and the content
*/
@OptIn(ExperimentalMaterialApi::class)
@Composable
inline fun TextButton(
noinline onClick: () -> Unit,
modifier: Modifier = Modifier,
enabled: Boolean = true,
interactionState: InteractionState = remember { InteractionState() },
elevation: ButtonElevation? = null,
shape: Shape = MaterialTheme.shapes.small,
border: BorderStroke? = null,
colors: ButtonColors = ButtonDefaults.textButtonColors(),
contentPadding: PaddingValues = ButtonDefaults.TextButtonContentPadding,
noinline content: @Composable RowScope.() -> Unit
) = Button(
onClick = onClick,
modifier = modifier,
enabled = enabled,
interactionState = interactionState,
elevation = elevation,
shape = shape,
border = border,
colors = colors,
contentPadding = contentPadding,
content = content
)
/**
* Represents the elevation for a button in different states.
*
* See [ButtonDefaults.elevation] for the default elevation used in a [Button].
*/
@ExperimentalMaterialApi
@Stable
interface ButtonElevation {
/**
* Represents the elevation used in a button, depending on [enabled] and [interactionState].
*
* @param enabled whether the button is enabled
* @param interactionState the [InteractionState] for this button
*/
fun elevation(enabled: Boolean, interactionState: InteractionState): Dp
}
/**
* Represents the background and content colors used in a button in different states.
*
* See [ButtonDefaults.buttonColors] for the default colors used in a [Button].
* See [ButtonDefaults.outlinedButtonColors] for the default colors used in a
* [OutlinedButton].
* See [ButtonDefaults.textButtonColors] for the default colors used in a [TextButton].
*/
@ExperimentalMaterialApi
@Stable
interface ButtonColors {
/**
* Represents the background color for this button, depending on [enabled].
*
* @param enabled whether the button is enabled
*/
fun backgroundColor(enabled: Boolean): Color
/**
* Represents the content color for this button, depending on [enabled].
*
* @param enabled whether the button is enabled
*/
fun contentColor(enabled: Boolean): Color
}
/**
* Contains the default values used by [Button]
*/
@Deprecated(
"ButtonConstants has been replaced with ButtonDefaults",
ReplaceWith(
"ButtonDefaults",
"androidx.compose.material.ButtonDefaults"
)
)
object ButtonConstants {
private val ButtonHorizontalPadding = 16.dp
private val ButtonVerticalPadding = 8.dp
/**
* The default content padding used by [Button]
*/
val DefaultContentPadding = PaddingValues(
start = ButtonHorizontalPadding,
top = ButtonVerticalPadding,
end = ButtonHorizontalPadding,
bottom = ButtonVerticalPadding
)
/**
* The default min width applied for the [Button].
* Note that you can override it by applying Modifier.widthIn directly on [Button].
*/
val DefaultMinWidth = 64.dp
/**
* The default min width applied for the [Button].
* Note that you can override it by applying Modifier.heightIn directly on [Button].
*/
val DefaultMinHeight = 36.dp
/**
* The default size of the icon when used inside a [Button].
*
* @sample androidx.compose.material.samples.ButtonWithIconSample
*/
val DefaultIconSize = 18.dp
/**
* The default size of the spacing between an icon and a text when they used inside a [Button].
*
* @sample androidx.compose.material.samples.ButtonWithIconSample
*/
val DefaultIconSpacing = 8.dp
// TODO: b/152525426 add support for focused and hovered states
/**
* Creates a [ButtonElevation] that will animate between the provided values according to the
* Material specification for a [Button].
*
* @param defaultElevation the elevation to use when the [Button] is enabled, and has no
* other [Interaction]s.
* @param pressedElevation the elevation to use when the [Button] is enabled and
* is [Interaction.Pressed].
* @param disabledElevation the elevation to use when the [Button] is not enabled.
*/
@OptIn(ExperimentalMaterialApi::class)
@Composable
@Deprecated(
"ButtonConstants has been replaced with ButtonDefaults",
ReplaceWith(
"ButtonDefaults.elevation(elevation, pressedElevation, disabledElevation)",
"androidx.compose.material.ButtonDefaults"
)
)
fun defaultElevation(
defaultElevation: Dp = 2.dp,
pressedElevation: Dp = 8.dp,
// focused: Dp = 4.dp,
// hovered: Dp = 4.dp,
disabledElevation: Dp = 0.dp
): ButtonElevation {
val clock = AmbientAnimationClock.current.asDisposableClock()
return remember(defaultElevation, pressedElevation, disabledElevation, clock) {
DefaultButtonElevation(
defaultElevation = defaultElevation,
pressedElevation = pressedElevation,
disabledElevation = disabledElevation,
clock = clock
)
}
}
/**
* Creates a [ButtonColors] that represents the default background and content colors used in
* a [Button].
*
* @param backgroundColor the background color of this [Button] when enabled
* @param disabledBackgroundColor the background color of this [Button] when not enabled
* @param contentColor the content color of this [Button] when enabled
* @param disabledContentColor the content color of this [Button] when not enabled
*/
@OptIn(ExperimentalMaterialApi::class)
@Composable
@Deprecated(
"ButtonConstants has been replaced with ButtonDefaults",
ReplaceWith(
"ButtonDefaults.buttonColors(backgroundColor, disabledBackgroundColor, contentColor, " +
"disabledContentColor)",
"androidx.compose.material.ButtonDefaults"
)
)
fun defaultButtonColors(
backgroundColor: Color = MaterialTheme.colors.primary,
disabledBackgroundColor: Color = MaterialTheme.colors.onSurface.copy(alpha = 0.12f)
.compositeOver(MaterialTheme.colors.surface),
contentColor: Color = contentColorFor(backgroundColor),
disabledContentColor: Color = MaterialTheme.colors.onSurface
.copy(alpha = ContentAlpha.disabled)
): ButtonColors = DefaultButtonColors(
backgroundColor,
disabledBackgroundColor,
contentColor,
disabledContentColor
)
/**
* Creates a [ButtonColors] that represents the default background and content colors used in
* an [OutlinedButton].
*
* @param backgroundColor the background color of this [OutlinedButton]
* @param contentColor the content color of this [OutlinedButton] when enabled
* @param disabledContentColor the content color of this [OutlinedButton] when not enabled
*/
@OptIn(ExperimentalMaterialApi::class)
@Composable
@Deprecated(
"ButtonConstants has been replaced with ButtonDefaults",
ReplaceWith(
"ButtonDefaults.outlinedButtonColors(backgroundColor, disabledBackgroundColor, " +
"contentColor, disabledContentColor)",
"androidx.compose.material.ButtonDefaults"
)
)
fun defaultOutlinedButtonColors(
backgroundColor: Color = MaterialTheme.colors.surface,
contentColor: Color = MaterialTheme.colors.primary,
disabledContentColor: Color = MaterialTheme.colors.onSurface
.copy(alpha = ContentAlpha.disabled)
): ButtonColors = DefaultButtonColors(
backgroundColor,
backgroundColor,
contentColor,
disabledContentColor
)
/**
* Creates a [ButtonColors] that represents the default background and content colors used in
* a [TextButton].
*
* @param backgroundColor the background color of this [TextButton]
* @param contentColor the content color of this [TextButton] when enabled
* @param disabledContentColor the content color of this [TextButton] when not enabled
*/
@OptIn(ExperimentalMaterialApi::class)
@Composable
@Deprecated(
"ButtonConstants has been replaced with ButtonDefaults",
ReplaceWith(
"ButtonDefaults.textButtonColors(backgroundColor, disabledBackgroundColor, " +
"contentColor, disabledContentColor)",
"androidx.compose.material.ButtonDefaults"
)
)
fun defaultTextButtonColors(
backgroundColor: Color = Color.Transparent,
contentColor: Color = MaterialTheme.colors.primary,
disabledContentColor: Color = MaterialTheme.colors.onSurface
.copy(alpha = ContentAlpha.disabled)
): ButtonColors = DefaultButtonColors(
backgroundColor,
backgroundColor,
contentColor,
disabledContentColor
)
/**
* The default color opacity used for an [OutlinedButton]'s border color
*/
const val OutlinedBorderOpacity = 0.12f
/**
* The default [OutlinedButton]'s border size
*/
val OutlinedBorderSize = 1.dp
/**
* The default disabled content color used by all types of [Button]s
*/
val defaultOutlinedBorder: BorderStroke
@Composable
get() = BorderStroke(
OutlinedBorderSize, MaterialTheme.colors.onSurface.copy(alpha = OutlinedBorderOpacity)
)
private val TextButtonHorizontalPadding = 8.dp
/**
* The default content padding used by [TextButton]
*/
val DefaultTextContentPadding = DefaultContentPadding.copy(
start = TextButtonHorizontalPadding,
end = TextButtonHorizontalPadding
)
}
/**
* Contains the default values used by [Button]
*/
object ButtonDefaults {
private val ButtonHorizontalPadding = 16.dp
private val ButtonVerticalPadding = 8.dp
/**
* The default content padding used by [Button]
*/
val ContentPadding = PaddingValues(
start = ButtonHorizontalPadding,
top = ButtonVerticalPadding,
end = ButtonHorizontalPadding,
bottom = ButtonVerticalPadding
)
/**
* The default min width applied for the [Button].
* Note that you can override it by applying Modifier.widthIn directly on [Button].
*/
val MinWidth = 64.dp
/**
* The default min width applied for the [Button].
* Note that you can override it by applying Modifier.heightIn directly on [Button].
*/
val MinHeight = 36.dp
/**
* The default size of the icon when used inside a [Button].
*
* @sample androidx.compose.material.samples.ButtonWithIconSample
*/
val IconSize = 18.dp
/**
* The default size of the spacing between an icon and a text when they used inside a [Button].
*
* @sample androidx.compose.material.samples.ButtonWithIconSample
*/
val IconSpacing = 8.dp
// TODO: b/152525426 add support for focused and hovered states
/**
* Creates a [ButtonElevation] that will animate between the provided values according to the
* Material specification for a [Button].
*
* @param defaultElevation the elevation to use when the [Button] is enabled, and has no
* other [Interaction]s.
* @param pressedElevation the elevation to use when the [Button] is enabled and
* is [Interaction.Pressed].
* @param disabledElevation the elevation to use when the [Button] is not enabled.
*/
@OptIn(ExperimentalMaterialApi::class)
@Composable
fun elevation(
defaultElevation: Dp = 2.dp,
pressedElevation: Dp = 8.dp,
// focused: Dp = 4.dp,
// hovered: Dp = 4.dp,
disabledElevation: Dp = 0.dp
): ButtonElevation {
val clock = AmbientAnimationClock.current.asDisposableClock()
return remember(defaultElevation, pressedElevation, disabledElevation, clock) {
DefaultButtonElevation(
defaultElevation = defaultElevation,
pressedElevation = pressedElevation,
disabledElevation = disabledElevation,
clock = clock
)
}
}
/**
* Creates a [ButtonColors] that represents the default background and content colors used in
* a [Button].
*
* @param backgroundColor the background color of this [Button] when enabled
* @param disabledBackgroundColor the background color of this [Button] when not enabled
* @param contentColor the content color of this [Button] when enabled
* @param disabledContentColor the content color of this [Button] when not enabled
*/
@OptIn(ExperimentalMaterialApi::class)
@Composable
fun buttonColors(
backgroundColor: Color = MaterialTheme.colors.primary,
disabledBackgroundColor: Color = MaterialTheme.colors.onSurface.copy(alpha = 0.12f)
.compositeOver(MaterialTheme.colors.surface),
contentColor: Color = contentColorFor(backgroundColor),
disabledContentColor: Color = MaterialTheme.colors.onSurface
.copy(alpha = ContentAlpha.disabled)
): ButtonColors = DefaultButtonColors(
backgroundColor,
disabledBackgroundColor,
contentColor,
disabledContentColor
)
/**
* Creates a [ButtonColors] that represents the default background and content colors used in
* an [OutlinedButton].
*
* @param backgroundColor the background color of this [OutlinedButton]
* @param contentColor the content color of this [OutlinedButton] when enabled
* @param disabledContentColor the content color of this [OutlinedButton] when not enabled
*/
@OptIn(ExperimentalMaterialApi::class)
@Composable
fun outlinedButtonColors(
backgroundColor: Color = MaterialTheme.colors.surface,
contentColor: Color = MaterialTheme.colors.primary,
disabledContentColor: Color = MaterialTheme.colors.onSurface
.copy(alpha = ContentAlpha.disabled)
): ButtonColors = DefaultButtonColors(
backgroundColor,
backgroundColor,
contentColor,
disabledContentColor
)
/**
* Creates a [ButtonColors] that represents the default background and content colors used in
* a [TextButton].
*
* @param backgroundColor the background color of this [TextButton]
* @param contentColor the content color of this [TextButton] when enabled
* @param disabledContentColor the content color of this [TextButton] when not enabled
*/
@OptIn(ExperimentalMaterialApi::class)
@Composable
fun textButtonColors(
backgroundColor: Color = Color.Transparent,
contentColor: Color = MaterialTheme.colors.primary,
disabledContentColor: Color = MaterialTheme.colors.onSurface
.copy(alpha = ContentAlpha.disabled)
): ButtonColors = DefaultButtonColors(
backgroundColor,
backgroundColor,
contentColor,
disabledContentColor
)
/**
* The default color opacity used for an [OutlinedButton]'s border color
*/
const val OutlinedBorderOpacity = 0.12f
/**
* The default [OutlinedButton]'s border size
*/
val OutlinedBorderSize = 1.dp
/**
* The default disabled content color used by all types of [Button]s
*/
val outlinedBorder: BorderStroke
@Composable
get() = BorderStroke(
OutlinedBorderSize, MaterialTheme.colors.onSurface.copy(alpha = OutlinedBorderOpacity)
)
private val TextButtonHorizontalPadding = 8.dp
/**
* The default content padding used by [TextButton]
*/
val TextButtonContentPadding = ContentPadding.copy(
start = TextButtonHorizontalPadding,
end = TextButtonHorizontalPadding
)
}
/**
* Default [ButtonElevation] implementation.
*/
@OptIn(ExperimentalMaterialApi::class)
@Stable
private class DefaultButtonElevation(
private val defaultElevation: Dp,
private val pressedElevation: Dp,
private val disabledElevation: Dp,
private val clock: AnimationClockObservable
) : ButtonElevation {
private val lazyAnimatedElevation = LazyAnimatedValue<Dp, AnimationVector1D> { target ->
AnimatedValueModel(initialValue = target, typeConverter = Dp.VectorConverter, clock = clock)
}
override fun elevation(enabled: Boolean, interactionState: InteractionState): Dp {
val interaction = interactionState.value.lastOrNull {
it is Interaction.Pressed
}
val target = if (!enabled) {
disabledElevation
} else {
when (interaction) {
Interaction.Pressed -> pressedElevation
else -> defaultElevation
}
}
val animatedElevation = lazyAnimatedElevation.animatedValueForTarget(target)
if (animatedElevation.targetValue != target) {
if (!enabled) {
// No transition when moving to a disabled state
animatedElevation.snapTo(target)
} else {
val lastInteraction = when (animatedElevation.targetValue) {
pressedElevation -> Interaction.Pressed
else -> null
}
animatedElevation.animateElevation(
from = lastInteraction,
to = interaction,
target = target
)
}
}
return animatedElevation.value
}
}
/**
* Default [ButtonColors] implementation.
*/
@OptIn(ExperimentalMaterialApi::class)
@Immutable
private class DefaultButtonColors(
private val backgroundColor: Color,
private val disabledBackgroundColor: Color,
private val contentColor: Color,
private val disabledContentColor: Color
) : ButtonColors {
override fun backgroundColor(enabled: Boolean): Color {
return if (enabled) backgroundColor else disabledBackgroundColor
}
override fun contentColor(enabled: Boolean): Color {
return if (enabled) contentColor else disabledContentColor
}
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other == null || this::class != other::class) return false
other as DefaultButtonColors
if (backgroundColor != other.backgroundColor) return false
if (disabledBackgroundColor != other.disabledBackgroundColor) return false
if (contentColor != other.contentColor) return false
if (disabledContentColor != other.disabledContentColor) return false
return true
}
override fun hashCode(): Int {
var result = backgroundColor.hashCode()
result = 31 * result + disabledBackgroundColor.hashCode()
result = 31 * result + contentColor.hashCode()
result = 31 * result + disabledContentColor.hashCode()
return result
}
}