Skip to content

Instantly share code, notes, and snippets.

@mishamoix
Last active February 27, 2025 13:55
Show Gist options
  • Save mishamoix/c1a0b0d52dddcfd3d69df5906091e21a to your computer and use it in GitHub Desktop.
Save mishamoix/c1a0b0d52dddcfd3d69df5906091e21a to your computer and use it in GitHub Desktop.
SwiftUI animation. @namespace and .matchedGeometryEffect
import SwiftUI
struct ContentView: View {
@State private var isProfileExpanded = false
@Namespace private var profileAnimation
private let gradient = LinearGradient(
gradient: Gradient(colors: [.purple, .orange]),
startPoint: .topLeading,
endPoint: .bottomTrailing
)
private let gradient2 = LinearGradient(
gradient: Gradient(colors: [.green, .yellow]),
startPoint: .topLeading,
endPoint: .bottomTrailing
)
var body: some View {
VStack {
if isProfileExpanded {
expandedProfileView
} else {
collapsedProfileView
}
videoList
}
}
var collapsedProfileView: some View {
HStack {
profileImage
.matchedGeometryEffect(id: "profileAvatar", in: profileAnimation)
.frame(width: 60, height: 60)
VStack(alignment: .leading) {
Text("Profile Name")
.font(.title)
.bold()
.matchedGeometryEffect(id: "profileName", in: profileAnimation)
Text("iOS Developer")
.foregroundColor(.secondary)
.matchedGeometryEffect(id: "profileJob", in: profileAnimation)
}
Spacer()
}
.padding()
}
var expandedProfileView: some View {
VStack {
profileImage
.matchedGeometryEffect(id: "profileAvatar", in: profileAnimation)
.frame(width: 130, height: 130)
VStack {
Text("Profile Name")
.font(.title)
.bold()
.matchedGeometryEffect(id: "profileName", in: profileAnimation)
Text("iOS Developer")
.foregroundColor(.pink)
.matchedGeometryEffect(id: "profileJob", in: profileAnimation)
Text("Check this Cool description, Check this Cool description, Check this Cool description.")
.padding()
}
}
.padding()
}
var profileImage: some View {
RoundedRectangle(cornerSize: CGSize(width: 6, height: 6))
.fill(isProfileExpanded ? gradient : gradient2)
.onTapGesture {
withAnimation(.spring()) {
isProfileExpanded.toggle()
}
}
}
var videoList: some View {
List {
ForEach(0...5, id: \.self) { _ in
ZStack {
RoundedRectangle(cornerRadius: 8)
.frame(height: 180)
.foregroundColor(.gray.opacity(0.5))
Image(systemName: "play.fill")
.resizable()
.frame(width: 30, height: 30)
.opacity(0.3)
}
.padding(.vertical)
}
.listRowSeparator(.hidden)
}
.listStyle(.plain)
}
}
#Preview {
ContentView()
.preferredColorScheme(.dark)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment