Merge "Introduce Scale indication for TV Compose" into androidx-main
diff --git a/tv/tv-material/api/public_plus_experimental_current.txt b/tv/tv-material/api/public_plus_experimental_current.txt
index 6793ddd..8a14d13 100644
--- a/tv/tv-material/api/public_plus_experimental_current.txt
+++ b/tv/tv-material/api/public_plus_experimental_current.txt
@@ -37,44 +37,30 @@
}
@androidx.compose.runtime.Immutable @androidx.tv.material3.ExperimentalTvMaterial3Api public final class ClickableSurfaceColor {
- method public long getColor();
- method public long getDisabledColor();
- method public long getFocusedColor();
- method public long getPressedColor();
- property public final long color;
- property public final long disabledColor;
- property public final long focusedColor;
- property public final long pressedColor;
}
@androidx.tv.material3.ExperimentalTvMaterial3Api public final class ClickableSurfaceDefaults {
method @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public androidx.tv.material3.ClickableSurfaceColor color(optional long color, optional long focusedColor, optional long pressedColor, optional long disabledColor);
method @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public androidx.tv.material3.ClickableSurfaceColor contentColor(optional long color, optional long focusedColor, optional long pressedColor, optional long disabledColor);
method public androidx.tv.material3.ClickableSurfaceGlow glow(optional androidx.tv.material3.Glow glow, optional androidx.tv.material3.Glow focusedGlow, optional androidx.tv.material3.Glow pressedGlow);
+ method public androidx.tv.material3.ClickableSurfaceScale scale(optional @FloatRange(from=0.0) float scale, optional @FloatRange(from=0.0) float focusedScale, optional @FloatRange(from=0.0) float pressedScale, optional @FloatRange(from=0.0) float disabledScale, optional @FloatRange(from=0.0) float focusedDisabledScale);
method @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public androidx.tv.material3.ClickableSurfaceShape shape(optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.ui.graphics.Shape focusedShape, optional androidx.compose.ui.graphics.Shape pressedShape, optional androidx.compose.ui.graphics.Shape disabledShape, optional androidx.compose.ui.graphics.Shape focusedDisabledShape);
field public static final androidx.tv.material3.ClickableSurfaceDefaults INSTANCE;
}
@androidx.compose.runtime.Immutable @androidx.tv.material3.ExperimentalTvMaterial3Api public final class ClickableSurfaceGlow {
- method public androidx.tv.material3.Glow getFocusedGlow();
- method public androidx.tv.material3.Glow getGlow();
- method public androidx.tv.material3.Glow getPressedGlow();
- property public final androidx.tv.material3.Glow focusedGlow;
- property public final androidx.tv.material3.Glow glow;
- property public final androidx.tv.material3.Glow pressedGlow;
+ }
+
+ @androidx.compose.runtime.Immutable @androidx.tv.material3.ExperimentalTvMaterial3Api public final class ClickableSurfaceScale {
+ field public static final androidx.tv.material3.ClickableSurfaceScale.Companion Companion;
+ }
+
+ public static final class ClickableSurfaceScale.Companion {
+ method public androidx.tv.material3.ClickableSurfaceScale getNone();
+ property public final androidx.tv.material3.ClickableSurfaceScale None;
}
@androidx.compose.runtime.Immutable @androidx.tv.material3.ExperimentalTvMaterial3Api public final class ClickableSurfaceShape {
- method public androidx.compose.ui.graphics.Shape getDisabledShape();
- method public androidx.compose.ui.graphics.Shape getFocusedDisabledShape();
- method public androidx.compose.ui.graphics.Shape getFocusedShape();
- method public androidx.compose.ui.graphics.Shape getPressedShape();
- method public androidx.compose.ui.graphics.Shape getShape();
- property public final androidx.compose.ui.graphics.Shape disabledShape;
- property public final androidx.compose.ui.graphics.Shape focusedDisabledShape;
- property public final androidx.compose.ui.graphics.Shape focusedShape;
- property public final androidx.compose.ui.graphics.Shape pressedShape;
- property public final androidx.compose.ui.graphics.Shape shape;
}
@androidx.compose.runtime.Stable @androidx.tv.material3.ExperimentalTvMaterial3Api public final class ColorScheme {
@@ -172,6 +158,7 @@
}
@androidx.compose.runtime.Stable @androidx.tv.material3.ExperimentalTvMaterial3Api public final class GlowIndication implements androidx.compose.foundation.Indication {
+ ctor public GlowIndication(long color, androidx.compose.ui.graphics.Shape shape, float glowBlurRadius, float offsetX, float offsetY);
method @androidx.compose.runtime.Composable public androidx.compose.foundation.IndicationInstance rememberUpdatedInstance(androidx.compose.foundation.interaction.InteractionSource interactionSource);
}
@@ -214,6 +201,11 @@
method @androidx.compose.runtime.Composable @androidx.tv.material3.ExperimentalTvMaterial3Api public static void MaterialTheme(optional androidx.tv.material3.ColorScheme colorScheme, optional androidx.tv.material3.Shapes shapes, optional androidx.tv.material3.Typography typography, kotlin.jvm.functions.Function0<kotlin.Unit> content);
}
+ @androidx.compose.runtime.Stable @androidx.tv.material3.ExperimentalTvMaterial3Api public final class ScaleIndication implements androidx.compose.foundation.Indication {
+ ctor public ScaleIndication(float scale);
+ method @androidx.compose.runtime.Composable public androidx.compose.foundation.IndicationInstance rememberUpdatedInstance(androidx.compose.foundation.interaction.InteractionSource interactionSource);
+ }
+
@androidx.tv.material3.ExperimentalTvMaterial3Api public sealed interface ScrollPauseHandle {
method public void resumeAutoScroll();
}
@@ -248,7 +240,7 @@
}
public final class SurfaceKt {
- method @androidx.compose.runtime.Composable @androidx.compose.runtime.NonRestartableComposable @androidx.tv.material3.ExperimentalTvMaterial3Api public static void Surface(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional float tonalElevation, optional androidx.tv.material3.ClickableSurfaceShape shape, optional androidx.tv.material3.ClickableSurfaceColor color, optional androidx.tv.material3.ClickableSurfaceColor contentColor, optional androidx.tv.material3.ClickableSurfaceGlow glow, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit> content);
+ method @androidx.compose.runtime.Composable @androidx.compose.runtime.NonRestartableComposable @androidx.tv.material3.ExperimentalTvMaterial3Api public static void Surface(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional float tonalElevation, optional androidx.tv.material3.ClickableSurfaceShape shape, optional androidx.tv.material3.ClickableSurfaceColor color, optional androidx.tv.material3.ClickableSurfaceColor contentColor, optional androidx.tv.material3.ClickableSurfaceScale scale, optional androidx.tv.material3.ClickableSurfaceGlow glow, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit> content);
method public static androidx.compose.runtime.ProvidableCompositionLocal<androidx.compose.ui.unit.Dp> getLocalAbsoluteTonalElevation();
property public static final androidx.compose.runtime.ProvidableCompositionLocal<androidx.compose.ui.unit.Dp> LocalAbsoluteTonalElevation;
}
diff --git a/tv/tv-material/src/androidTest/java/androidx/tv/material3/SurfaceTest.kt b/tv/tv-material/src/androidTest/java/androidx/tv/material3/SurfaceTest.kt
index 6976d6d..b630f44 100644
--- a/tv/tv-material/src/androidTest/java/androidx/tv/material3/SurfaceTest.kt
+++ b/tv/tv-material/src/androidTest/java/androidx/tv/material3/SurfaceTest.kt
@@ -18,6 +18,7 @@
import android.os.Build
import androidx.annotation.RequiresApi
+import androidx.compose.foundation.background
import androidx.compose.foundation.gestures.awaitEachGesture
import androidx.compose.foundation.interaction.FocusInteraction
import androidx.compose.foundation.interaction.Interaction
@@ -34,6 +35,7 @@
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.testutils.assertContainsColor
+import androidx.compose.testutils.assertDoesNotContainColor
import androidx.compose.testutils.assertShape
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
@@ -55,6 +57,7 @@
import androidx.compose.ui.test.captureToImage
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onNodeWithTag
+import androidx.compose.ui.test.onRoot
import androidx.compose.ui.test.performKeyInput
import androidx.compose.ui.test.performSemanticsAction
import androidx.compose.ui.test.pressKey
@@ -432,4 +435,30 @@
.captureToImage()
.assertContainsColor(Color.Green)
}
+
+ @RequiresApi(Build.VERSION_CODES.O)
+ @Test
+ fun clickableSurface_onFocus_changesScaleFactor() {
+ rule.setContent {
+ Box(
+ modifier = Modifier
+ .background(Color.Blue)
+ .size(50.toDp())
+ )
+ Surface(
+ onClick = {},
+ modifier = Modifier
+ .size(50.toDp())
+ .testTag("surface"),
+ scale = ClickableSurfaceDefaults.scale(
+ focusedScale = 1.5f
+ )
+ ) {}
+ }
+ rule.onRoot().captureToImage().assertContainsColor(Color.Blue)
+
+ rule.onNodeWithTag("surface").performSemanticsAction(SemanticsActions.RequestFocus)
+
+ rule.onRoot().captureToImage().assertDoesNotContainColor(Color.Blue)
+ }
}
diff --git a/tv/tv-material/src/main/java/androidx/tv/material3/Indications.kt b/tv/tv-material/src/main/java/androidx/tv/material3/Indications.kt
index 7202baa..0eb0b30 100644
--- a/tv/tv-material/src/main/java/androidx/tv/material3/Indications.kt
+++ b/tv/tv-material/src/main/java/androidx/tv/material3/Indications.kt
@@ -16,12 +16,20 @@
package androidx.tv.material3
+import androidx.compose.animation.core.CubicBezierEasing
+import androidx.compose.animation.core.TweenSpec
import androidx.compose.animation.core.animateDpAsState
+import androidx.compose.animation.core.animateFloatAsState
+import androidx.compose.animation.core.tween
import androidx.compose.foundation.Indication
import androidx.compose.foundation.IndicationInstance
+import androidx.compose.foundation.interaction.FocusInteraction
+import androidx.compose.foundation.interaction.Interaction
import androidx.compose.foundation.interaction.InteractionSource
+import androidx.compose.foundation.interaction.PressInteraction
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Stable
+import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.graphics.Color
@@ -31,6 +39,7 @@
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.graphics.drawscope.ContentDrawScope
import androidx.compose.ui.graphics.drawscope.drawIntoCanvas
+import androidx.compose.ui.graphics.drawscope.scale
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.Density
@@ -44,7 +53,7 @@
*/
@ExperimentalTvMaterial3Api
@Stable
-class GlowIndication internal constructor(
+class GlowIndication(
private val color: Color,
private val shape: Shape,
private val glowBlurRadius: Dp,
@@ -152,3 +161,60 @@
offsetY = offsetX
)
}
+
+internal object ScaleIndicationTokens {
+ const val focusDuration: Int = 300
+ const val unFocusDuration: Int = 500
+ const val pressedDuration: Int = 120
+ const val releaseDuration: Int = 300
+ val enterEasing = CubicBezierEasing(0f, 0f, 0.2f, 1f)
+}
+
+/**
+ * ScaleIndication is an [Indication] that scales the composable by the provided factor. This
+ * indication by default will create a smooth animation between the state changes.
+ */
+@ExperimentalTvMaterial3Api
+@Stable
+class ScaleIndication(private val scale: Float) : Indication {
+ @Composable
+ override fun rememberUpdatedInstance(interactionSource: InteractionSource): IndicationInstance {
+ val interaction by interactionSource.interactions.collectAsState(
+ initial = FocusInteraction.Focus()
+ )
+
+ val animationSpec = defaultScaleAnimationSpec(interaction)
+
+ val animatedScale by animateFloatAsState(
+ targetValue = scale,
+ animationSpec = animationSpec
+ )
+
+ return remember(animatedScale, animationSpec) {
+ ScaleIndicationInstance(scale = animatedScale)
+ }
+ }
+
+ private fun defaultScaleAnimationSpec(interaction: Interaction): TweenSpec<Float> =
+ tween(
+ durationMillis = when (interaction) {
+ is FocusInteraction.Focus -> ScaleIndicationTokens.focusDuration
+ is FocusInteraction.Unfocus -> ScaleIndicationTokens.unFocusDuration
+ is PressInteraction.Press -> ScaleIndicationTokens.pressedDuration
+ is PressInteraction.Release -> ScaleIndicationTokens.releaseDuration
+ is PressInteraction.Cancel -> ScaleIndicationTokens.releaseDuration
+ else -> ScaleIndicationTokens.releaseDuration
+ },
+ easing = ScaleIndicationTokens.enterEasing
+ )
+}
+
+internal class ScaleIndicationInstance(
+ private val scale: Float
+) : IndicationInstance {
+ override fun ContentDrawScope.drawIndication() {
+ scale(scale) {
+ [email protected]()
+ }
+ }
+}
diff --git a/tv/tv-material/src/main/java/androidx/tv/material3/Surface.kt b/tv/tv-material/src/main/java/androidx/tv/material3/Surface.kt
index 3b7fdb4..7d2555f 100644
--- a/tv/tv-material/src/main/java/androidx/tv/material3/Surface.kt
+++ b/tv/tv-material/src/main/java/androidx/tv/material3/Surface.kt
@@ -40,7 +40,6 @@
import androidx.compose.ui.draw.drawWithCache
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.graphics.drawOutline
import androidx.compose.ui.graphics.graphicsLayer
@@ -54,7 +53,6 @@
import androidx.compose.ui.unit.Density
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
-import androidx.compose.ui.zIndex
import kotlinx.coroutines.launch
/**
@@ -74,6 +72,7 @@
* @param shape Defines the surface's shape.
* @param color Color to be used on background of the Surface
* @param contentColor The preferred content color provided by this Surface to its children.
+ * @param scale Defines size of the Surface relative to its original size.
* @param glow Diffused shadow to be shown behind the Surface.
* @param interactionSource the [MutableInteractionSource] representing the stream of [Interaction]s
* for this Surface. You can create and pass in your own remembered [MutableInteractionSource] if
@@ -92,6 +91,7 @@
shape: ClickableSurfaceShape = ClickableSurfaceDefaults.shape(),
color: ClickableSurfaceColor = ClickableSurfaceDefaults.color(),
contentColor: ClickableSurfaceColor = ClickableSurfaceDefaults.contentColor(),
+ scale: ClickableSurfaceScale = ClickableSurfaceDefaults.scale(),
glow: ClickableSurfaceGlow = ClickableSurfaceDefaults.glow(),
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
content: @Composable (BoxScope.() -> Unit)
@@ -102,8 +102,11 @@
modifier = modifier.tvClickable(
enabled = enabled,
onClick = onClick,
- interactionSource = interactionSource
+ interactionSource = interactionSource,
+ value = false,
+ onValueChanged = null
),
+ selected = false,
enabled = enabled,
tonalElevation = tonalElevation,
shape = ClickableSurfaceDefaults.shape(
@@ -124,6 +127,12 @@
pressed = pressed,
color = contentColor
),
+ scale = ClickableSurfaceDefaults.scale(
+ enabled = enabled,
+ focused = focused,
+ pressed = pressed,
+ scale = scale
+ ),
glow = ClickableSurfaceDefaults.glow(
enabled = enabled,
focused = focused,
@@ -138,14 +147,15 @@
@ExperimentalTvMaterial3Api
@Composable
private fun SurfaceImpl(
- modifier: Modifier = Modifier,
- selected: Boolean = false,
+ modifier: Modifier,
+ selected: Boolean,
enabled: Boolean,
- shape: Shape = RectangleShape,
+ shape: Shape,
color: Color,
contentColor: Color,
+ scale: Float,
glow: Glow,
- tonalElevation: Dp = 0.dp,
+ tonalElevation: Dp,
interactionSource: MutableInteractionSource,
content: @Composable (BoxScope.() -> Unit)
) {
@@ -178,6 +188,10 @@
modifier = modifier
.indication(
interactionSource = interactionSource,
+ indication = remember(scale) { ScaleIndication(scale = scale) }
+ )
+ .indication(
+ interactionSource = interactionSource,
indication = rememberGlowIndication(
color = surfaceColorAtElevation(
color = glow.elevationColor,
@@ -235,9 +249,9 @@
*/
private fun Modifier.tvClickable(
enabled: Boolean,
- onClick: (() -> Unit)? = null,
- value: Boolean = false,
- onValueChanged: ((Boolean) -> Unit)? = null,
+ onClick: (() -> Unit)?,
+ value: Boolean,
+ onValueChanged: ((Boolean) -> Unit)?,
interactionSource: MutableInteractionSource
) = this
.handleDPadEnter(
@@ -335,10 +349,10 @@
selected: Boolean
): Float {
return when {
- enabled -> EnabledContentAlpha
!enabled && pressed -> DisabledPressedStateAlpha
!enabled && focused -> DisabledFocusedStateAlpha
!enabled && selected -> DisabledSelectedStateAlpha
+ enabled -> EnabledContentAlpha
else -> DisabledDefaultStateAlpha
}
}
diff --git a/tv/tv-material/src/main/java/androidx/tv/material3/SurfaceDefaults.kt b/tv/tv-material/src/main/java/androidx/tv/material3/SurfaceDefaults.kt
index 1a1ef5d..67f0697 100644
--- a/tv/tv-material/src/main/java/androidx/tv/material3/SurfaceDefaults.kt
+++ b/tv/tv-material/src/main/java/androidx/tv/material3/SurfaceDefaults.kt
@@ -16,6 +16,7 @@
package androidx.tv.material3
+import androidx.annotation.FloatRange
import androidx.compose.foundation.interaction.Interaction
import androidx.compose.runtime.Composable
import androidx.compose.runtime.ReadOnlyComposable
@@ -131,6 +132,48 @@
disabledColor = disabledColor
)
+ internal fun scale(
+ enabled: Boolean,
+ focused: Boolean,
+ pressed: Boolean,
+ scale: ClickableSurfaceScale
+ ): Float {
+ return when {
+ pressed && enabled -> scale.pressedScale
+ focused && enabled -> scale.focusedScale
+ focused && !enabled -> scale.focusedDisabledScale
+ enabled -> scale.scale
+ else -> scale.disabledScale
+ }
+ }
+
+ /**
+ * Creates a [ClickableSurfaceScale] that represents the default scales used in a
+ * Surface. scales are used to modify the size of a composable in different [Interaction]
+ * states e.g. 1f (original) in default state, 1.2f (scaled up) in focused state,
+ * 0.8f (scaled down) in pressed state, etc.
+ *
+ * @param scale the scale to be used for this Surface when enabled
+ * @param focusedScale the scale to be used for this Surface when focused
+ * @param pressedScale the scale to be used for this Surface when pressed
+ * @param disabledScale the scale to be used for this Surface when disabled
+ * @param focusedDisabledScale the scale to be used for this Surface when disabled and
+ * focused
+ */
+ fun scale(
+ @FloatRange(from = 0.0) scale: Float = 1f,
+ @FloatRange(from = 0.0) focusedScale: Float = 1.1f,
+ @FloatRange(from = 0.0) pressedScale: Float = scale,
+ @FloatRange(from = 0.0) disabledScale: Float = scale,
+ @FloatRange(from = 0.0) focusedDisabledScale: Float = disabledScale
+ ) = ClickableSurfaceScale(
+ scale = scale,
+ focusedScale = focusedScale,
+ pressedScale = pressedScale,
+ disabledScale = disabledScale,
+ focusedDisabledScale = focusedDisabledScale
+ )
+
internal fun glow(
enabled: Boolean,
focused: Boolean,
diff --git a/tv/tv-material/src/main/java/androidx/tv/material3/SurfaceStyles.kt b/tv/tv-material/src/main/java/androidx/tv/material3/SurfaceStyles.kt
index 60c1a7b..3cc05a5 100644
--- a/tv/tv-material/src/main/java/androidx/tv/material3/SurfaceStyles.kt
+++ b/tv/tv-material/src/main/java/androidx/tv/material3/SurfaceStyles.kt
@@ -16,6 +16,7 @@
package androidx.tv.material3
+import androidx.annotation.FloatRange
import androidx.compose.foundation.interaction.Interaction
import androidx.compose.runtime.Immutable
import androidx.compose.ui.graphics.Color
@@ -25,21 +26,15 @@
/**
* Defines [Shape] for all TV [Interaction] states of a Clickable Surface.
- * @param shape [Shape] to be applied when Clickable Surface is in the default state.
- * @param focusedShape [Shape] to be applied when Clickable Surface is focused.
- * @param pressedShape [Shape] to be applied when Clickable Surface is pressed.
- * @param disabledShape [Shape] to be applied when Clickable Surface is disabled.
- * @param focusedDisabledShape [Shape] to be applied when Clickable Surface is focused in the
- * default state.
*/
@ExperimentalTvMaterial3Api
@Immutable
class ClickableSurfaceShape internal constructor(
- val shape: Shape,
- val focusedShape: Shape,
- val pressedShape: Shape,
- val disabledShape: Shape,
- val focusedDisabledShape: Shape
+ internal val shape: Shape,
+ internal val focusedShape: Shape,
+ internal val pressedShape: Shape,
+ internal val disabledShape: Shape,
+ internal val focusedDisabledShape: Shape
) {
override fun equals(other: Any?): Boolean {
if (this === other) return true
@@ -75,18 +70,14 @@
/**
* Defines [Color] for all TV [Interaction] states of a Clickable Surface.
- * @param color [Color] to be applied when Clickable Surface is in the default state.
- * @param focusedColor [Color] to be applied when Clickable Surface is focused.
- * @param pressedColor [Color] to be applied when Clickable Surface is pressed.
- * @param disabledColor [Color] to be applied when Clickable Surface is disabled.
*/
@ExperimentalTvMaterial3Api
@Immutable
class ClickableSurfaceColor internal constructor(
- val color: Color,
- val focusedColor: Color,
- val pressedColor: Color,
- val disabledColor: Color
+ internal val color: Color,
+ internal val focusedColor: Color,
+ internal val pressedColor: Color,
+ internal val disabledColor: Color
) {
override fun equals(other: Any?): Boolean {
if (this === other) return true
@@ -118,17 +109,73 @@
}
/**
+ * Defines the scale for all TV indication states of Surface. Note: This scale must be
+ * a non-negative float.
+ */
+@ExperimentalTvMaterial3Api
+@Immutable
+class ClickableSurfaceScale internal constructor(
+ @FloatRange(from = 0.0) internal val scale: Float,
+ @FloatRange(from = 0.0) internal val focusedScale: Float,
+ @FloatRange(from = 0.0) internal val pressedScale: Float,
+ @FloatRange(from = 0.0) internal val disabledScale: Float,
+ @FloatRange(from = 0.0) internal val focusedDisabledScale: Float
+) {
+ override fun equals(other: Any?): Boolean {
+ if (this === other) return true
+ if (other == null || this::class != other::class) return false
+
+ other as ClickableSurfaceScale
+
+ if (scale != other.scale) return false
+ if (focusedScale != other.focusedScale) return false
+ if (pressedScale != other.pressedScale) return false
+ if (disabledScale != other.disabledScale) return false
+ if (focusedDisabledScale != other.focusedDisabledScale) return false
+
+ return true
+ }
+
+ override fun hashCode(): Int {
+ var result = scale.hashCode()
+ result = 31 * result + focusedScale.hashCode()
+ result = 31 * result + pressedScale.hashCode()
+ result = 31 * result + disabledScale.hashCode()
+ result = 31 * result + focusedDisabledScale.hashCode()
+
+ return result
+ }
+
+ override fun toString(): String {
+ return "ClickableSurfaceScale(scale=$scale, focusedScale=$focusedScale," +
+ "pressedScale=$pressedScale, disabledScale=$disabledScale, " +
+ "focusedDisabledScale=$focusedDisabledScale)"
+ }
+
+ companion object {
+ /**
+ * Signifies the absence of a scale in TV Components. Use this if you do not want to
+ * display a [ScaleIndication] in any of the Leanback TV Components.
+ */
+ val None = ClickableSurfaceScale(
+ scale = 1f,
+ focusedScale = 1f,
+ pressedScale = 1f,
+ disabledScale = 1f,
+ focusedDisabledScale = 1f
+ )
+ }
+}
+
+/**
* Defines [Glow] for all TV states of [Surface].
- * @param glow [Glow] to be applied when [Surface] is in the default state.
- * @param focusedGlow [Glow] to be applied when [Surface] is focused.
- * @param pressedGlow [Glow] to be applied when [Surface] is pressed.
*/
@ExperimentalTvMaterial3Api
@Immutable
class ClickableSurfaceGlow internal constructor(
- val glow: Glow,
- val focusedGlow: Glow,
- val pressedGlow: Glow
+ internal val glow: Glow,
+ internal val focusedGlow: Glow,
+ internal val pressedGlow: Glow
) {
override fun equals(other: Any?): Boolean {
if (this === other) return true