如何将 LazyVGrid 单元格与 TabView 中相应的全屏图像连接起来 (Xcode 13, iOS15)
How to connect LazyVGrid cells with the corresponding full screen images in a TabView (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-\([=12=])") }
let wallpaperSet = (1...50).map { Wallpaper(name: "iridisfera-wallpaper-\([=12=])") }
图库
(我删除了我的 selectedTab 实验,所以你可以直接插入你的代码)
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 必须位于单独的结构中,因此可以使用已经 selected 的选项卡对其进行初始化。 TabView 中的图像需要 .tag()
才能为 selection 识别它们。
它还不能很好地工作,因为你的图像无法识别,但它应该给你方向。单独使用索引是不安全的,所以你应该把它们放在一个可识别的结构中,并通过 id select。
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) )
}
}
从相应的选项卡缩小时,我很难匹配正确的网格单元格。
刚开始学习,我一定要再看几个教程。如果你想在这里伸出援手,提前谢谢你。
这是代码:
型号
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-\([=12=])") }
let wallpaperSet = (1...50).map { Wallpaper(name: "iridisfera-wallpaper-\([=12=])") }
图库 (我删除了我的 selectedTab 实验,所以你可以直接插入你的代码)
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 必须位于单独的结构中,因此可以使用已经 selected 的选项卡对其进行初始化。 TabView 中的图像需要 .tag()
才能为 selection 识别它们。
它还不能很好地工作,因为你的图像无法识别,但它应该给你方向。单独使用索引是不安全的,所以你应该把它们放在一个可识别的结构中,并通过 id select。
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) )
}
}