ANDROIDX / COMPOSE / MATERIAL 3
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 示例。
源码依据
- 默认 shapes:
Button.kt:1165-1188 - 按高度选择:
Button.kt:1541-1562 - 官方示例:
ButtonSamples.kt:49-124 - 公共 API:
material3/api/current.txt中的 Button overloads 与ButtonShapes