SwiftUI 模仿Photos App
xcode 13.4.1, swift 5.5, iOS 15.4
2022-08-20
這篇就講講如何用自定議畫面的跳轉來模仿Photos App。
1. 首先做一個初始畫面,照片的列表。
import SwiftUI
struct ContentView : View {
@State var photoNames = ["cat1", "cat2", "cat3", "cat4", "cat5"]
@State var selectedPhotoName = "cat2"
@State var isSelected = false
var body: some View {
HStack {
if !isSelected {
VStack {
HStack {
ForEach(photoNames, id:\.self) { name in
Image(name)
.resizable()
.scaledToFit()
}
}
Spacer()
}
} else {
}
}
}
}
2. 然後做一個選了一個照片後,放大圖片的頁面。
import SwiftUI
struct ContentView : View {
@State var photoNames = ["cat1", "cat2", "cat3", "cat4", "cat5"]
@State var selectedPhotoName = "cat2"
@State var isSelected = true
var body: some View {
VStack {
if !isSelected {
HStack {
ForEach(photoNames, id:\.self) { name in
Image(name)
.resizable()
.scaledToFit()
}
}
Spacer()
} else {
Image(selectedPhotoName)
.resizable()
.scaledToFit()
}
}
}
}
3. 只要改變isSelected就切換圖片列表和放大圖片。
import SwiftUI
struct ContentView : View {
@State var photoNames = ["cat1", "cat2", "cat3", "cat4", "cat5"]
@State var selectedPhotoName = "cat2"
@State var isSelected = false
var body: some View {
VStack {
if !isSelected {
HStack {
ForEach(photoNames, id:\.self) { name in
Image(name)
.resizable()
.scaledToFit()
.onTapGesture {
withAnimation {
isSelected.toggle()
}
}
}
}
Spacer()
} else {
Image(selectedPhotoName)
.resizable()
.scaledToFit()
.onTapGesture {
withAnimation {
isSelected.toggle()
}
}
}
}
}
}
4. 為了顯示放大點選的圖片,用selectedPhotoName來記住點選了哪一個圖片的名字。
import SwiftUI
struct ContentView : View {
@State var photoNames = ["cat1", "cat2", "cat3", "cat4", "cat5"]
@State var selectedPhotoName = "cat2"
@State var isSelected = false
var body: some View {
VStack {
if !isSelected {
HStack {
ForEach(photoNames, id:\.self) { name in
Image(name)
.resizable()
.scaledToFit()
.onTapGesture {
selectedPhotoName = name
withAnimation {
isSelected.toggle()
}
}
}
}
Spacer()
} else {
Image(selectedPhotoName)
.resizable()
.scaledToFit()
.onTapGesture {
withAnimation {
isSelected.toggle()
}
}
}
}
}
}
5. 最後使用SwiftUI提供了一個方法@Namespace和matchedGeometryEffect來做到切換頁面時動畫:
import SwiftUI
struct ContentView : View {
@Namespace var namespace
@State var photoNames = ["cat1", "cat2", "cat3", "cat4", "cat5"]
@State var selectedPhotoName = "cat2"
@State var isSelected = false
var body: some View {
VStack {
if !isSelected {
HStack {
ForEach(photoNames, id:\.self) { name in
Image(name)
.resizable()
.scaledToFit()
.matchedGeometryEffect(id: name, in: namespace)
.onTapGesture {
selectedPhotoName = name
withAnimation {
isSelected.toggle()
}
}
}
}
Spacer()
} else {
Image(selectedPhotoName)
.resizable()
.scaledToFit()
.matchedGeometryEffect(id: selectedPhotoName, in: namespace)
.onTapGesture {
withAnimation {
isSelected.toggle()
}
}
}
}
}
}