Glass Element 作为 navigationTransition 源时为何出现反向动画异常?
结论
这段代码没有明显的 matchedTransitionSource 配对错误,源视图和目标视图使用了相同的 ID 与 namespace。仅凭高亮停留后突然恢复的现象,还无法判断这是否属于预期行为,也不能确定是否有业务状态未重置。
可以先调整 sheet 的高度,尝试让它保持非全高时的玻璃外观。如果界面必须使用全高 sheet,且目标系统上仍有异常,更直接的规避方式是移除 .navigationTransition(.zoom(...)),使用默认 sheet 转场。
为什么看起来像高亮没有消失
交互高亮和转场期间的背景变化需要分开排查。示例没有自行维护按压状态,也没有显式设置高亮。Apple 的设计说明指出,sheet 的外观会随高度变化:半高 sheet 使用 Liquid Glass,扩展到全高时会变得更加不透明。参见 Apple 的 Liquid Glass 适配说明。
一种可能的解释是,反向 zoom 转场期间,源区域暂时呈现了与 sheet 背景相关的外观,转场结束后才恢复原本的玻璃效果,看起来就像高亮突然消失。这仍是需要验证的排查假设,不能据此确定系统内部的具体原因。
matchedTransitionSource 用于标记导航转场的源视图,其配置闭包可以调整源视图的外观。不过,相关文档没有提供专门控制这种“高亮恢复时机”的选项。参见 API 文档。
先尝试调整 sheet 高度
先用 .medium 做对照,观察关闭动画是否改善。如果需要接近全高的布局,可以再试 .fraction(0.98)。
将原示例中的 .sheet 改为:
.sheet(isPresented: $present) {
Text("")
.presentationDetents([.fraction(0.98)])
.navigationTransition(
.zoom(sourceID: "source", in: namespace)
)
}
其余代码保持原样。测试半高效果时,将停靠点替换为:
.presentationDetents([.medium])
.fraction(_:) 定义相对高度的停靠点,.medium 是系统提供的约半高停靠点。参见 PresentationDetent 文档。
0.98 是用于测试接近全高布局的数值,不能当作修复开关。能否改善问题,需要在目标设备和系统上确认,系统也没有承诺这个比例一定保留某种背景材质。调整高度还会改变 sheet 的实际布局,需要检查内容展示是否合适。
如果必须保留全高布局
先暂时移除 .navigationTransition,保留普通 sheet:
.sheet(isPresented: $present) {
Text("")
}
如果异常随之消失,就可以将排查范围进一步缩小到 zoom 转场与玻璃外观的组合。产品允许的话,可以直接采用默认转场。
如果全高 sheet 和 zoom 都必须保留,应记录出现问题的系统版本,并用同一份最小示例在其他目标系统上复测。如果问题持续复现,可以通过 Feedback Assistant 提交示例和录屏。在有对应修复说明或经过实际验证之前,不宜宣称某个版本已经解决了问题。
注意事项
- 分别测试下拉关闭和代码触发关闭,也要检查下拉后取消关闭的情况。
- 不要通过固定延时、切换
.id()或重建源视图来强行恢复外观,这些操作会引入额外的时序或视图身份变化。 - Apple Podcasts 的效果可以作为视觉参考,但无法证明它使用了相同的 SwiftUI 视图结构和转场实现。
备注:内容仅供参考。
