SwiftUI 如何实现类iOS静音模式的HUD弹窗及图标动画效果
你可以通过新增状态变量控制动画触发,结合SwiftUI内置动画修饰符实现需求,修改后的完整代码如下:
struct ContentView_Previews: PreviewProvider { static var previews: some View { PopOver(image: "speaker.slash.fill", color: .gray, title: "静音已开启") } } struct PopOver: View{ var image: String var color: Color var title: String @Environment(\.colorScheme) var scheme // 控制图标动画状态 @State private var animateIcon = false // 控制HUD垂直偏移,初始在屏幕外 @State private var offsetY: CGFloat = -100 var body: some View{ HStack(spacing: 10){ Image(systemName: image) .font(.title3) .foregroundColor(color) // 以下两种动画效果二选一即可 // 效果1:沿Y轴旋转180度 .rotation3DEffect(.degrees(animateIcon ? 180 : 0), axis: (x: 0, y: 1, z: 0)) // 效果2:左右轻微晃动10度 // .rotationEffect(.degrees(animateIcon ? -10 : 10)) Text(title) .foregroundColor(.primary) } .padding(.vertical,10) .padding(.horizontal) .background( scheme == .dark ? Color.black : Color.white ) .clipShape(Capsule()) .shadow(color: Color.primary.opacity(0.1), radius: 5, x: 1, y: 5) .shadow(color: Color.primary.opacity(0.03), radius: 5, x: 0, y: -5) .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .top) .offset(y: offsetY) .onAppear { // HUD从顶部滑入动画 withAnimation(.easeOut(duration: 0.3)) { offsetY = 20 } // 触发图标动画 withAnimation(.easeInOut(duration: 0.4).repeatCount(1, autoreverses: true)) { animateIcon = true } // 停留2秒后HUD滑出消失 DispatchQueue.main.asyncAfter(deadline: .now() + 2) { withAnimation(.easeIn(duration: 0.3)) { offsetY = -100 } // 重置状态方便下次触发 DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { animateIcon = false } } } } }
如果需要在父视图中手动触发HUD展示,可以参考如下调用方式:
struct ContentView: View { // 控制HUD显隐状态 @State private var showMuteHUD = false var body: some View { ZStack { Button("切换静音状态") { showMuteHUD = true } if showMuteHUD { PopOver(image: "speaker.slash.fill", color: .gray, title: "静音已开启") .onDisappear { // HUD消失后重置状态 showMuteHUD = false } } } } }
你可以根据需求调整动画时长、旋转角度、停留时间等参数,匹配你想要的效果。
内容的提问来源于stack exchange,提问作者SwiftUIRookie
相关产品推荐
相关产品推荐

