iOS 26 SwiftUI:如何为交互式玻璃效果条件设色调且不中断动画?
解决SwiftUI交互式玻璃效果色调切换时动画中断的问题
问题原因
你遇到的动画中断问题,本质是每次通过三元表达式切换tint时,都会创建全新的GlassEffectStyle实例。SwiftUI会将这种变化识别为修饰符的完全替换,而非同一修饰符的属性更新,从而中断原有交互式玻璃效果的动画流程。
解决方案
核心思路是让色调变化成为连续的可动画属性,而非创建新的玻璃效果样式。以下是两种可行实现:
1. 透明度过渡(适用于同色系深浅切换)
如果只是调整色调的透明度,直接修改opacity而非切换颜色实例,配合withAnimation实现平滑过渡:
.overlay(alignment: .topTrailing) { Button(action: { withAnimation(.easeInOut) { saved.toggle() } }) { Image(saved ? "bookmark" : "bookmark.outline") .resizable() .scaledToFit() .frame(width: 14, height: 14) .foregroundStyle(.white) .padding(8) } .glassEffect( .clear .tint(overlayCol.opacity(saved ? 1 : 0.1)) .interactive() ) .padding(.top, 8) .padding(.trailing, 8) }
2. 跨颜色平滑过渡(适用于不同色调切换)
如果需要在完全不同的颜色间切换,利用SwiftUI对Color的原生动画支持,通过计算属性返回目标颜色,并配合显式动画:
// 定义目标色调的计算属性 private var targetTint: Color { saved ? .blue : .orange // 替换为你的实际颜色 } // 视图部分 .overlay(alignment: .topTrailing) { Button(action: { withAnimation(.easeInOut(duration: 0.3)) { saved.toggle() } }) { Image(saved ? "bookmark" : "bookmark.outline") .resizable() .scaledToFit() .frame(width: 14, height: 14) .foregroundStyle(.white) .padding(8) } .glassEffect( .clear .tint(targetTint) .interactive() ) .padding(.top, 8) .padding(.trailing, 8) }
原理说明
原生应用(如Phone的筛选按钮、Reminders的工具栏按钮)的实现逻辑一致:通过让色调变化成为同一修饰符的可动画属性更新,而非替换整个玻璃效果样式,从而保留交互式动画的连续性。SwiftUI会自动处理颜色/透明度的平滑过渡,不会中断原有玻璃效果的交互动画流程。
内容的提问来源于stack exchange,提问作者koza
相关产品推荐
相关产品推荐

