skip to Main Content

I have LazyVGrid in which i want to make 2 item per row for iPhone and 4 per row in iPad, I am not sure how should i give condition in SwiftUI and how to restrict number of rows

//
//  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

Answers


  1. Well you can make your gridItemLayout to the following:

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

    And add in an init (recommended) or in .onAppear:

    if UI_USER_INTERFACE_IDIOM() == .pad {
        gridItemLayout.append(contentsOf: [GridItem(spacing: 2), GridItem(spacing: 2)]) //your spacing
    }
    
    Login or Signup to reply.
  2. Something like this:

    LazyVGrid(columns: Array(repeating: .init(.flexible()),
                            count: UIDevice.current.userInterfaceIdiom == .pad ? 4 : 2)) {
            ForEach(categories, id: .name) { category in
                        
            }
    }
    
    Login or Signup to reply.
  3. While the provided answers will work per se they can get tricky when using your app in a multitasking mode on the iPad: Split View or Slide Over. In case of Slide Over the width of your app on the iPad will be the same as it would be on the iPhone but if you’ll check for the interface idiom, you’ll still get .pad (well, cause you are using iPad). And the interface therefore might get broken – you’ll get an iPad interface on an iPhone-sized app.

    But there’s a way to do it right – UserInterfaceSizeClass. Specifically you’ll need a horizontal size class. This enum has 2 cases (state of February 2023): .compact and .regular. In simple words the UserInterfaceSizeClass is .compact when the width of an app is similar to the iPhone’s width (Slide Over or Slit View in Portrait Mode or just an actual iPhone) and .regular when the width is similar to the iPad’s width (normal iPad Portrait or Landscape mode, Split View in Landscape Mode). Based on this parameter you can decide how to render your interface

    So, enough theory, here’s the code to copy-paste 🙂

    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) {
                ...
            }
        }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search