Button:从静态圆角到按压形变
理解 Button 的普通重载与 ButtonShapes 重载,以及 shapes() 和 shapesFor(height) 的区别。
为什么主题开了,按钮还没变形
Button 同时保留了普通 shape: Shape 重载和新的 shapes: ButtonShapes 重载。只有后者持有“常态形状 + 按压形状”,才能在交互状态之间变化。
官方 sample 的最小用法就是:
Button(
onClick = {},
shapes = ButtonDefaults.shapes(),
) {
Text("Button")
}这也是为什么不能只靠 MaterialExpressiveTheme 自动给所有按钮增加形变:是否使用新重载,是组件调用点自己选择的。
shapes() 和 shapesFor(height)
shapes()
直接返回当前主题缓存的默认 ButtonShapes。源码使用 small button token 的常态与按压形状。
shapesFor(height)
先按给定高度归入 extra small / small / medium / large / extra large 档,再选择相应 pressedShape。
因此,标准小按钮可以用 shapes();当你明确使用不同容器高度时,shapesFor(buttonHeight) 能让按压形状与尺寸档位匹配。
val height = ButtonDefaults.LargeContainerHeight
Button(
onClick = {},
modifier = Modifier.heightIn(min = height),
shapes = ButtonDefaults.shapesFor(height),
) {
Text("Large action")
}自定义两种状态
Button(
onClick = {},
shapes = ButtonDefaults.shapes(
shape = RoundedCornerShape(24.dp),
pressedShape = RoundedCornerShape(8.dp),
),
) {
Text("Morph")
}ButtonShapes 的两个 shape 都是 CornerBasedShape 时,形状才能按实现预期平滑插值。自定义前先保证交互反馈没有损害文字空间和可点击区域。
哪些按钮支持
当前 public API 中,Button、ElevatedButton、FilledTonalButton、OutlinedButton 与 TextButton 都有接收 ButtonShapes 的重载;官方 samples 也分别提供了 animated shape 示例。
复制即用
按下变形的按钮,复制即用:
import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
@Composable
fun MorphButton() {
// 最小用法:形状随按压状态变化
Button(
onClick = {},
shapes = ButtonDefaults.shapes(),
) {
Text("Button")
}
}
@Composable
fun LargeMorphButton() {
// 大按钮:按压形状与尺寸档位匹配
val height = ButtonDefaults.LargeContainerHeight
Button(
onClick = {},
modifier = Modifier.heightIn(min = height),
shapes = ButtonDefaults.shapesFor(height),
) {
Text("Large action")
}
}
@Composable
fun CustomMorphButton() {
// 自定义常态与按压形状
Button(
onClick = {},
shapes = ButtonDefaults.shapes(
shape = RoundedCornerShape(24.dp),
pressedShape = RoundedCornerShape(8.dp),
),
) {
Text("Morph")
}
}ElevatedButton、FilledTonalButton、OutlinedButton、TextButton 都有接收 ButtonShapes 的相同重载,替换类名即可。