SwiftUI共享视图几何信息的@Namespace属性包装器
SwiftUI共享视图几何信息的@Namespace属性包装器

SwiftUI共享视图几何信息的@Namespace属性包装器

@Namespace 是 SwiftUI 中的一个属性包装器,用于创建动画的共享命名空间。它主要应用于 SwiftUI 的匹配几何效果(MatchedGeometryEffect),以在两个视图之间实现平滑的过渡动画。

基本概念

@Namespace 创建一个标识符,供视图间共享。使用该标识符时,SwiftUI 能够将视图的几何信息(如位置、大小)关联起来,从而计算出它们之间的动画路径。

使用场景

1、视图过渡动画

在两个视图之间进行元素的平滑过渡。

2、重用同一个视图的几何信息

动态调整视图的布局和动画。

基本语法

@Namespace private var animationNamespace

1、声明一个 @Namespace 属性。

2、使用 .matchedGeometryEffect(id:namespace:) 修饰视图,并为其指定唯一的 ID 和命名空间。

示例

视图间的平滑过渡

struct MatchedGeometryExample: View {
    @Namespace private var namespace
    @State private var isExpanded = false

    var body: some View {
        VStack {
            if isExpanded {
                RoundedRectangle(cornerRadius: 25)
                    .fill(Color.blue)
                    .matchedGeometryEffect(id: "shape", in: namespace)
                    .frame(width: 300, height: 300)
                    .onTapGesture {
                        withAnimation {
                            isExpanded.toggle()
                        }
                    }
            } else {
                RoundedRectangle(cornerRadius: 25)
                    .fill(Color.blue)
                    .matchedGeometryEffect(id: "shape", in: namespace)
                    .frame(width: 100, height: 100)
                    .onTapGesture {
                        withAnimation {
                            isExpanded.toggle()
                        }
                    }
            }
        }
    }
}

解析

@Namespace:用于创建动画共享空间。

matchedGeometryEffect:将两个视图连接到同一个动画空间,通过相同的 id 和 namespace 实现过渡效果。

withAnimation:触发动画,SwiftUI 自动计算动画路径。

运行效果:点击小矩形时,视图平滑过渡到大矩形的位置和尺寸。

动态列表中的动画

@Namespace 在动态内容(如列表或网格)中也非常有用,用于在视图的插入、删除、移动之间实现动画。

struct DynamicListExample: View {
    @Namespace private var namespace
    @State private var items = ["Apple", "Banana", "Cherry", "Date"]

    var body: some View {
        VStack {
            ForEach(items, id: \.self) { item in
                Text(item)
                    .font(.headline)
                    .padding()
                    .background(Color.yellow)
                    .cornerRadius(10)
                    .matchedGeometryEffect(id: item, in: namespace)
            }
            Button("Delete Item") {
                withAnimation {
                    if !items.isEmpty {
                        items.remove(at: items.count - 1)
                    }
                }
            }
            Button("Add Item") {
                withAnimation {
                    items.append("New Item \(items.count + 1)")
                }
            }
        }
    }
}

运行效果:当添加或删除元素时,视图的位置和内容会通过平滑动画更新。

关键点总结

1、声明命名空间

使用 @Namespace 创建命名空间,确保动画的关联性。

2、使用 matchedGeometryEffect

通过设置相同的 id 和 namespace,SwiftUI 知道哪些视图应该共享动画。

3、支持动态布局

动态列表或复杂布局中,@Namespace 能显著提升动画效果。

高级用法

多个元素同步动画

@Namespace 可以为多个元素同步动画,例如一个列表项的图片和文本。

struct MultipleElementsExample: View {
    @Namespace private var namespace
    @State private var isExpanded = false

    var body: some View {
        VStack {
            if isExpanded {
                VStack {
                    Image(systemName: "star.fill")
                        .font(.largeTitle)
                        .foregroundColor(.yellow)
                        .matchedGeometryEffect(id: "icon", in: namespace)
                    
                    Text("Favorite Item")
                        .font(.headline)
                        .matchedGeometryEffect(id: "text", in: namespace)
                }
                .onTapGesture {
                    withAnimation {
                        isExpanded.toggle()
                    }
                }
            } else {
                HStack {
                    Image(systemName: "star.fill")
                        .font(.title)
                        .foregroundColor(.yellow)
                        .matchedGeometryEffect(id: "icon", in: namespace)
                    
                    Text("Favorite Item")
                        .font(.subheadline)
                        .matchedGeometryEffect(id: "text", in: namespace)
                }
                .onTapGesture {
                    withAnimation {
                        isExpanded.toggle()
                    }
                }
            }
        }
    }
}

运行效果:点击视图时,图片和文本同步过渡到新位置。

@Namespace 是 SwiftUI 中非常强大的工具,特别适合用来实现平滑过渡动画,提升界面交互效果。通过正确管理动画的命名空间和几何效果,可以显著优化用户体验。

如果您认为这篇文章给您带来了帮助,您可以在此通过支付宝或者微信打赏网站开放者。

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注