ui: move the action press flourish onto the shape, spin the gear
The press animation turned the glyph; put it on the scalloped cookie container instead and make it stronger (scale 1→0.82, rotate 0→40°). The glyph holds upright via a counter-rotation, so the shape spins while a magnifier or list icon stays readable. New spinIcon opts a glyph into its own quarter turn — the settings gear uses it, so it reads as a gear cranking. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -31,8 +31,10 @@ import androidx.graphics.shapes.RoundedPolygon
|
|||||||
* its own [shape] and [containerColor], so a row of them reads as a set of
|
* its own [shape] and [containerColor], so a row of them reads as a set of
|
||||||
* distinct little tokens rather than identical grey glyphs.
|
* distinct little tokens rather than identical grey glyphs.
|
||||||
*
|
*
|
||||||
* Pressing springs the icon down a touch and gives it a small turn — a light
|
* Pressing springs the whole shape down and gives it a turn — the scalloped
|
||||||
* expressive flourish, no library motion APIs needed.
|
* container is what dips and spins, while the glyph inside stays upright (a
|
||||||
|
* spinning magnifier or list icon would just read as wrong). [spinIcon] opts a
|
||||||
|
* glyph into turning too, for icons that read well mid-spin like the gear.
|
||||||
*/
|
*/
|
||||||
@OptIn(ExperimentalMaterial3ExpressiveApi::class)
|
@OptIn(ExperimentalMaterial3ExpressiveApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
@@ -46,15 +48,25 @@ fun ShapedActionButton(
|
|||||||
contentColor: Color = MaterialTheme.colorScheme.onTertiaryContainer,
|
contentColor: Color = MaterialTheme.colorScheme.onTertiaryContainer,
|
||||||
size: Dp = 40.dp,
|
size: Dp = 40.dp,
|
||||||
iconSize: Dp = 22.dp,
|
iconSize: Dp = 22.dp,
|
||||||
|
spinIcon: Boolean = false,
|
||||||
) {
|
) {
|
||||||
val interaction = remember { MutableInteractionSource() }
|
val interaction = remember { MutableInteractionSource() }
|
||||||
val pressed by interaction.collectIsPressedAsState()
|
val pressed by interaction.collectIsPressedAsState()
|
||||||
val scale by animateFloatAsState(if (pressed) 0.88f else 1f, label = "actionScale")
|
// The shape (the scalloped cookie) turns and dips on press.
|
||||||
val rotation by animateFloatAsState(if (pressed) 24f else 0f, label = "actionRotation")
|
val shapeRotation by animateFloatAsState(if (pressed) 40f else 0f, label = "shapeRotation")
|
||||||
|
val scale by animateFloatAsState(if (pressed) 0.82f else 1f, label = "shapeScale")
|
||||||
|
// The glyph's *net* turn: 0 keeps it upright, spinIcon gives it a quarter turn.
|
||||||
|
val iconRotation by animateFloatAsState(
|
||||||
|
if (pressed && spinIcon) 90f else 0f,
|
||||||
|
label = "iconRotation",
|
||||||
|
)
|
||||||
|
|
||||||
Surface(
|
Surface(
|
||||||
onClick = onClick,
|
onClick = onClick,
|
||||||
modifier = modifier.size(size),
|
modifier = modifier
|
||||||
|
.size(size)
|
||||||
|
.scale(scale)
|
||||||
|
.rotate(shapeRotation),
|
||||||
shape = shape.toShape(),
|
shape = shape.toShape(),
|
||||||
color = containerColor,
|
color = containerColor,
|
||||||
contentColor = contentColor,
|
contentColor = contentColor,
|
||||||
@@ -64,10 +76,11 @@ fun ShapedActionButton(
|
|||||||
Icon(
|
Icon(
|
||||||
imageVector = icon,
|
imageVector = icon,
|
||||||
contentDescription = contentDescription,
|
contentDescription = contentDescription,
|
||||||
|
// Counter the container's turn so the glyph's net rotation is just
|
||||||
|
// [iconRotation] — upright by default, a quarter turn for the gear.
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.size(iconSize)
|
.size(iconSize)
|
||||||
.scale(scale)
|
.rotate(iconRotation - shapeRotation),
|
||||||
.rotate(rotation),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -285,6 +285,7 @@ private fun HomeTopBar(
|
|||||||
modifier = Modifier.padding(start = 8.dp),
|
modifier = Modifier.padding(start = 8.dp),
|
||||||
size = 48.dp,
|
size = 48.dp,
|
||||||
iconSize = 26.dp,
|
iconSize = 26.dp,
|
||||||
|
spinIcon = true,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user