iOS 26 Liquid Glass Gotcha:相邻按钮悄悄吞掉点击
Source: Dev.to
设置
两个按钮垂直堆叠,间距为 26 pt,使用标准的 VStack 布局:
VStack(spacing: 26) {
Spacer()
Button {
store.send(.signupButtonTapped)
} label: {
Text("Sign Up")
.padding()
.frame(width: buttonWidth, height: 55)
}
.glassEffect(.clear.interactive())
.buttonStyle(.plain)
Button {
store.send(.loginButtonTapped)
} label: {
Text("Log In")
.padding()
.frame(width: buttonWidth, height: 50)
}
.glassEffect(.clear.interactive())
.buttonStyle(.plain)
}

Sign Up 正常工作;Log In 没有任何响应。代码和修饰符完全相同——唯一的区别是它们的位置。
原因
在 未指定形状 的情况下调用 .glassEffect(.clear.interactive()) 默认将玻璃托盘设为矩形。在 iOS 26 中,Liquid Glass 系统会自动 合并 相互靠近的相邻玻璃表面为一个单一的交互组。
合并后,.interactive() 手势处理器会将点击事件路由到 层级中的第一个视图——本例中的注册 (Sign Up) 按钮。登录 (Log In) 按钮的点击被合并后的玻璃组静默消费,永远不会触发其对应的动作。
这种合并行为是有意为之(Apple 希望玻璃元素呈现为一个流体表面),但它对手势路由的副作用导致调试异常困难,因为没有任何可见错误。
修复
使用 in: 参数指定明确的形状:
// Before (broken)
.glassEffect(.clear.interactive())
// After (works)
.glassEffect(.clear.interactive(), in: .capsule)
为每个按钮指定不同的玻璃形状可防止自动合并,从而每个按钮都拥有自己的手势处理程序。
可复用的修饰符
如果你将玻璃效果包装在 ViewModifier 中以实现向后兼容,请确保包含形状:
struct GlassButtonModifier: ViewModifier {
func body(content: Content) -> some View {
if #available(iOS 26.0, *) {
content.glassEffect(.clear.interactive(), in: .capsule)
} else {
content
.background(.ultraThinMaterial, in: Capsule())
}
}
}
何时需要注意
此问题会在以下情况下出现:
- 两个或多个
.glassEffect()视图 相邻(例如,在VStack、HStack或ZStack中)。 - 您正在使用
.interactive()来提供按压/弹跳反馈。 - 您没有使用
in:指定形状。
这尤其危险,因为 第一个按钮始终有效,因此问题可能在用户报告按钮失效之前不被注意到。
TL;DR
| 变体 | 形状(默认) | 合并? | 点击行为 |
|---|---|---|---|
.glassEffect(.clear.interactive()) | 矩形 | 是 | 仅第一个按钮接收点击 |
.glassEffect(.clear.interactive(), in: .capsule) | 胶囊 | 否 | 所有按钮均接收点击 |
在相邻视图上使用 .interactive() 时,务必为 .glassEffect() 传入形状。
未来的你会感谢现在的你。