如何在TabView中将LazyVGrid单元格与相应的全屏图像连接起来(Xcode 13,iOS15)



从相应的选项卡缩小时,我很难匹配正确的网格单元格。

刚开始学习,我肯定应该再学习一些教程。如果你想在这里伸出援手,请提前感谢。

这是代码:

型号

struct Thumbnail: Identifiable {
let id = UUID()
var name: String
}
struct Wallpaper: Identifiable {
var id = UUID()
var name: String
}
let thumbnailSet = (1...50).map { Thumbnail(name: "iridisfera-thumbnail-($0)") }
let wallpaperSet = (1...50).map { Wallpaper(name: "iridisfera-wallpaper-($0)") }

画廊(我删除了我选择的Tab实验,这样你就可以直接插入你的代码(

struct GalleryView: View {
@Namespace var namespace
@State private var fullScreen: Int? = nil
@State private var selectedTab = 0

let columns = [GridItem(.flexible(), spacing: 2), GridItem(.flexible())]

var body: some View {
ZStack {
// MARK: GRID VIEW
ScrollView(showsIndicators: false) {
LazyVGrid(columns: columns, spacing: 2) {
ForEach(thumbnailSet.indices) { index in

let fullscreenIndex = fullScreen
if index == fullscreenIndex {
Color.clear
} else {
Image(thumbnailSet[index].name)
.resizable()
.aspectRatio(0.5, contentMode: .fit)
.matchedGeometryEffect(id: index, in: namespace)
.onTapGesture {
withAnimation(.interpolatingSpring(mass: 0.2, stiffness: 34, damping: 4)) {fullScreen = index}
}
}
}
}
}
.ignoresSafeArea()

// MARK: FULL SCREEN VIEW
if let fullscreenIndex = fullScreen {
TabView(selection: $selectedTab) {
ForEach(wallpaperSet.indices) { index in

Image(wallpaperSet[index].name)
.resizable()
.ignoresSafeArea()
.scaledToFill()
}
}
.tabViewStyle(PageTabViewStyle(indexDisplayMode: .never))
.matchedGeometryEffect(id: fullscreenIndex, in: namespace)
.ignoresSafeArea()
.zIndex(1)
.onTapGesture {
withAnimation(.interpolatingSpring(mass: 0.1, stiffness: 28, damping: 4)) {fullScreen = nil}
}
}
}
}
}

此代码显示了一般方法。TabView必须在一个单独的结构中,这样它就可以用已经选择的选项卡进行初始化。TabView中的图像需要有.tag()来识别它们以进行选择
它还不能完美工作,因为您的图像无法识别,但它应该为您指明方向。单独使用索引是不安全的,所以你应该把它们放在一个可识别的结构中,并通过id进行选择。

struct GalleryView: View {

@Namespace var namespace
@State private var fullScreen: Int? = nil

let columns = [GridItem(.flexible(), spacing: 2), GridItem(.flexible())]

var body: some View {
ZStack {
// MARK: GRID VIEW
ScrollView(showsIndicators: false) {
LazyVGrid(columns: columns, spacing: 2) {
ForEach(thumbnailSet.indices) { index in

if index == fullScreen {
Color.clear
} else {
Image(thumbnailSet[index].name)
.resizable()
.aspectRatio(1, contentMode: .fill)
.matchedGeometryEffect(id: index, in: namespace)
.onTapGesture {
withAnimation {
fullScreen = index
}
}
}
}
}
}
.ignoresSafeArea()

// MARK: FULL SCREEN VIEW
if fullScreen != nil {
FullscreenTabView(selectedImage: $fullScreen, ns: namespace)
}
}
}
}

struct FullscreenTabView: View {

@Binding var selectedImage: Int?
var ns: Namespace.ID

init(selectedImage: Binding<Int?>, ns: Namespace.ID) {
self._selectedImage = selectedImage
self.ns = ns
// initialize selctedTab to selectedImage
self._selectedTab = State(initialValue: selectedImage.wrappedValue ?? 0)
}

@State private var selectedTab: Int

var body: some View {
TabView(selection: $selectedTab) {

ForEach(wallpaperSet.indices) { index in

Image(wallpaperSet[index].name)
.resizable()
.tag(index) // << the images in TabView need tags to identify
.ignoresSafeArea()
.matchedGeometryEffect(id: index == selectedTab ? selectedTab : 0,
in: ns, isSource: true)

.onTapGesture {
withAnimation {
selectedImage = nil
}
}
}
}
.ignoresSafeArea()
.tabViewStyle(.page(indexDisplayMode: .never) )
}
}

最新更新