如何在 LazyVGrid 中设置 iPhone 和 iPad 的项目数量?

3

我有一个LazyVGrid,我想在iPhone上每行放2个项目,在iPad上每行放4个项目。 我不确定在SwiftUI中应该如何设置条件以及如何限制行数。

//
//  ContentView.swift
//  DemoProject


import SwiftUI
import CoreData

struct ContentView: View {
    @Environment(\.managedObjectContext) private var viewContext

    @FetchRequest(
        sortDescriptors: [NSSortDescriptor(keyPath: \Item.timestamp, ascending: true)],
        animation: .default)
    private var items: FetchedResults<Item>
    private var gridItemLayout = [GridItem(.adaptive(minimum: 100))]

    @StateObject private var viewModel = HomeViewModel()

    var body: some View {
        GeometryReader { geometry in
            NavigationView {
                ScrollView {
                    LazyVGrid(columns: gridItemLayout, spacing: 20) {
                        ForEach(viewModel.results, id: \.self) {
                            let viewModel = ResultVM(model: $0)

                            NavigationLink(destination: {
                                DetailView()
                            }, label: {
                                SearchResultRow(resultVM: viewModel)

                            })
                        }
                    }
                }
            }
            .onAppear(perform: {
                viewModel.performSearch()
            })
        }
    }
}

struct SearchResultRow: View {

    let resultVM: ResultVM

    var body: some View {
        HStack {
            RoundedRectangle(cornerRadius: 16).fill(.yellow)
                .frame(maxWidth: .infinity).aspectRatio(1, contentMode: .fit)
                .overlay(Text(resultVM.trackName))
                .onTapGesture {
                }

        }.padding()
            .background(Color.red)
    }
}

enter image description here

3个回答

3

类似这样:

LazyVGrid(columns: Array(repeating: .init(.flexible()),
                        count: UIDevice.current.userInterfaceIdiom == .pad ? 4 : 2)) {
        ForEach(categories, id: \.name) { category in
                    
        }
}

0

你可以将你的gridItemLayout设置为以下内容:

private var gridItemLayout = [
    GridItem(spacing: 2),//your spacing
    GridItem(spacing: 2),//your spacing
]

在初始化中添加(推荐)或在.onAppear中添加:

if UI_USER_INTERFACE_IDIOM() == .pad {
    gridItemLayout.append(contentsOf: [GridItem(spacing: 2), GridItem(spacing: 2)]) //your spacing
}

0

虽然提供的答案本身可以工作,但在iPad上使用您的应用程序进行多任务处理时可能会变得棘手:分屏或滑动。在Slide Over的情况下,iPad上您的应用程序的宽度将与iPhone上的宽度相同,但是如果您检查界面习惯用语,仍将获得.pad(好吧,因为您正在使用iPad)。因此,界面可能会被破坏-您将在iPhone大小的应用程序上获得iPad界面。

但是有一种正确的方法-UserInterfaceSizeClass。具体而言,您需要一个水平大小类。这个枚举有两种情况(截至2023年2月):.compact.regular。简单地说,当应用程序的宽度类似于iPhone的宽度(Slide Over或Portrait模式下的Slit View或实际的iPhone)时,UserInterfaceSizeClass.compact,当宽度类似于iPad的宽度(正常的iPad Portrait或Landscape模式,Split View在Landscape模式下)时,它是.regular。根据此参数,您可以决定如何呈现您的界面

因此,足够的理论,这里是要复制粘贴的代码 :)

struct YourView: View {
    @Environment(\.horizontalSizeClass)
    var horizontalSizeClass

    var columns: [GridItem] {
        switch horizontalSizeClass {
        case .compact:
            return [GridItem(), GridItem()] // Using 2 columns if it's narrow
        case .regular:
            return [GridItem(), GridItem(), GridItem(), GridItem()] // Using 4 columns if it's wide
        // Cover `nil` and `@unknown default` here
        }
    }

    var body: some View {
        LazyVGrid(columns: columns) {
            ...
        }
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接