Как заставить простой SwiftUI загружаться как UITableView (логически!)

#swiftui #vstack

#swiftui #vstack

Вопрос:

Как я могу заставить SwiftUI загружать 8 изображений по горизонтали, но если третье изображение исчезает с экрана, оно помещается в Vstack под первым изображением с тем же заполнением… и если три могут поместиться на экране, он делает то же самое с 4-м.

Я все равно не могу найти, как это сделать! Просмотры таблиц было так просто реализовать, но теперь SwiftUI все намного усложняет

 iPhone:

[1] [2]
[3] [4]
[5] [6] 
[7] [8]

iPad Pro
[1] [2][3] [4]
[5] [6] [7] [8]

iPad Mini
[1] [2][3] 
[4] [5] [6] 
[7] [8]
  

Комментарии:

1. Вы можете взглянуть на LazyVGrid .

2. Я пытался реализовать это @pawello2222, даже с фреймингом он не организован правильно, и кнопки появляются за пределами экрана

Ответ №1:

Я выполнил это же требование с помощью приведенного ниже кода. Пожалуйста, проверьте.

Нам нужно рассчитать количество строк и столбцов на основе общего количества элементов

Логические —

  1. Вычислите столбцы, предполагая равную ширину для каждого изображения на экране
    • Ширина экрана / ширина каждой ячейки изображения
  2. Вычислите строки, разделив общее количество изображений в массиве на количество столбцов.
  3. Например;
  • Всего изображений в массиве — 5

  • Общее количество столбцов равно 2

  • Всего строк = 5/2 = 2,5 это означает, что нам нужна 3-я строка для отображения последнего изображения

 struct GalleryView: View {
    //Sample array of images
    let images: [String] = ["preview1","preview2","preview3","preview4","preview5""]
    let columns = Int(UIScreen.main.bounds.width/120.0) //image width is 100 and taken extra 20 for padding
    
    var body: some View {
        ScrollView {
            GalleryCellView(rows: getRows(), columns: columns) { index in
                if index < self.images.count {
                    Button(action: { }) {
                        ImageGridView(image: self.images[index])
                    }
                }
            }.listRowInsets(EdgeInsets())
        }
    }
    
    func getRows() -> Int {
        //calculate rows based on image count and total columns
        let rows = Double(images.count)/Double(columns)
        return floor(rows) == rows ? Int(rows) : Int(rows 1.0)
        //if number of rows is a double values that means one more row is needed
    }
}

//Load image button cell
struct ImageGridView: View {
    let image: String
    var body: some View {
        Image(image)
            .renderingMode(.original)
            .frame(width:100, height:100)
            .cornerRadius(10)
    }
}

//Build cell view
struct GalleryCellView<Content: View>: View {
    let rows: Int
    let columns: Int
    let content: (Int) -> Content
    
    var body: some View {
        VStack(alignment: .leading, spacing : 0) {
            ForEach(0 ..< rows, id: .self) { row in
                HStack(spacing : 10) {
                    ForEach(0 ..< self.columns, id: .self) { column in
                        self.content((row * self.columns)   column)
                    }
                }.padding([.top, .bottom] , 5)
                .padding([.leading,.trailing], 10)
            }
        }.padding(10)
    }

    init(rows: Int, columns: Int, @ViewBuilder content: @escaping (Int) -> Content) {
        self.rows = rows
        self.columns = columns
        self.content = content
    }
}
  

Протестировано в Xcode версии 11.3, iPhone 11 Pro Max и iPad Pro (12.9 —
дюймовые) симуляторы

Результат в iPhone

Результат в iPad