在 SwiftUI 中,transition 用于定义视图如何从屏幕上“进入”和“退出”。它常与 @State 和 if 条件配合,用于控制视图的显示和隐藏,同时可以实现精美的动画效果。
示例
.transition(.slide) // 使用滑动效果
基本用法
transition 定义视图在插入或移除时的动画方式。
import SwiftUI
struct ContentView: View {
@State private var isVisible = false
var body: some View {
VStack {
Button("Toggle View") {
withAnimation {
isVisible.toggle()
}
}
if isVisible {
Rectangle()
.fill(Color.blue)
.frame(width: 100, height: 100)
.transition(.slide) // 使用滑动效果
}
}
}
}
常见的内置 Transition 类型
1、.opacity:视图通过透明度渐入渐出
.transition(.opacity)
2、.slide:视图从屏幕边缘滑入或滑出
.transition(.slide)
3、.scale:视图通过缩放效果出现或消失
.transition(.scale)
4、.move(edge:):从指定的边缘移入或移出
.transition(.move(edge: .top))
5、.offset(x:y:):使用偏移量定义进入和退出动画
.transition(.offset(x:-100,y:100))
6、.asymmetric(insert:, remove:):为进入和移出分别设置动画
.transition(.asymmetric(insertion: .slide, removal: .opacity))
代码示例
示例 1:.opacity 和 .scale 组合
struct ContentView: View {
@State private var isVisible = false
var body: some View {
VStack {
Button("Toggle View") {
withAnimation {
isVisible.toggle()
}
}
if isVisible {
Circle()
.fill(Color.green)
.frame(width: 100, height: 100)
.transition(.opacity.combined(with: .scale)) // 同时使用透明度和缩放
}
}
}
}
效果:视图逐渐变大并淡入;移除时逐渐缩小并淡出。
示例 2:.move(edge:)
struct ContentView: View {
@State private var isVisible = false
var body: some View {
VStack {
Button("Toggle View") {
withAnimation {
isVisible.toggle()
}
}
if isVisible {
Rectangle()
.fill(Color.orange)
.frame(width: 200, height: 100)
.transition(.move(edge: .leading)) // 从左边缘移入移出
}
}
}
}
效果:视图从左侧滑入或滑出。
示例 3:.asymmetric(insert:, remove:)
asymmetric 允许为插入和移除视图指定不同的动画。
struct ContentView: View {
@State private var isVisible = false
var body: some View {
VStack {
Button("Toggle View") {
withAnimation {
isVisible.toggle()
}
}
if isVisible {
RoundedRectangle(cornerRadius: 20)
.fill(Color.purple)
.frame(width: 200, height: 100)
.transition(.asymmetric(
insertion: .scale, // 插入时缩放出现
removal: .move(edge: .bottom) // 移除时向下滑出
))
}
}
}
}
效果:
视图插入时有缩放动画。
视图移除时从底部滑出。
自定义 Transition
除了内置的 transition,还可以定义自己的过渡动画,使用 .modifier() 方法。
自定义示例:
struct ContentView: View {
@State private var isVisible = false
var body: some View {
VStack {
Button("Toggle View") {
withAnimation {
isVisible.toggle()
}
}
if isVisible {
Rectangle()
.fill(Color.red)
.frame(width: 200, height: 100)
.transition(.customTransition) // 自定义过渡
}
}
}
}
extension AnyTransition {
static var customTransition: AnyTransition {
AnyTransition.modifier(
active: CustomModifier(offset: 300, opacity: 0),
identity: CustomModifier(offset: 0, opacity: 1)
)
}
}
struct CustomModifier: ViewModifier {
var offset: CGFloat
var opacity: Double
func body(content: Content) -> some View {
content
.offset(x: offset)
.opacity(opacity)
}
}
效果:
插入时视图从屏幕外(x: 300)滑入并淡入。
移除时视图滑出屏幕并淡出。
添加 Transition 动画的条件
有时候,可能希望过渡动画仅在特定条件下生效,可以通过 if 或 .transaction 控制。
示例:
struct ContentView: View {
@State private var isVisible = false
@State private var enableTransition = true
var body: some View {
VStack {
Toggle("Enable Transition", isOn: $enableTransition)
.padding()
Button("Toggle View") {
if enableTransition {
withAnimation {
isVisible.toggle()
}
} else {
isVisible.toggle()
}
}
if isVisible {
Circle()
.fill(Color.blue)
.frame(width: 100, height: 100)
.transition(.scale)
}
}
}
}
总结
transition 用于控制视图的进入和退出动画,与 if 条件和 withAnimation 配合。
内置的 .opacity、.slide、.scale 等常见效果可以直接使用。
使用 .asymmetric 和 .modifier() 进行组合和自定义,可以实现复杂的动画需求。