Как создать макет типа Masonry с помощью сетки SwiftUI2? - PullRequest
0 голосов
/ 13 июля 2020

Может ли сеточная система SwiftUI 2 отображать макеты типа Masonry?

Макет Masonry будет выглядеть следующим образом:

Макет кладки изображения

Замечательной особенностью этого макета является то, что содержимое может охватывать несколько столбцов.

Это не кажется автоматически возможным с LazyVGrid или LazyHGrid, поскольку они полагаются на GridItem, который, кажется, описывает столбец (фиксированный, гибкий или адаптивный).

Если вы думаете в терминах столбца, такой дизайн не может быть достигнут.

Я что-то пропустил, или это правда, что мы не можем сделать такую ​​сетку ?

1 Ответ

1 голос
/ 16 июля 2020

Я должен признать, что я еще не провел большого исследования для Lazy Grids, но, увидев несколько примеров, я боюсь, что это будет невозможно. Но мое мышление программирования таково: все возможно . Итак, давайте сделаем собственное решение! Вот мой:

struct ContentView: View {
    let items = (1 ... 12).map { "Item \($0)" }
    var range: Range<Int> { 0 ..< Int((Double(items.count) / 3).rounded(.up)) }
    var body: some View {
        GeometryReader { geometry in
            ScrollView {
                LazyVStack { // still some laziness 
                    ForEach(range, id: \.self) { index in
                        HStack(spacing: 0) {
                            if index % 2 == 0 {
                                Text(items[index * 3])
                                    .frame(maxHeight: .infinity)
                                    .frame(width: geometry.size.width * 2/3)
                                    .background(Color(#colorLiteral(red: 0.3427395821, green: 0.7238617539, blue: 0.6179549098, alpha: 1)))
                                VStack(spacing: 0) {
                                    Text(items[index * 3 + 1])
                                        .frame(maxWidth: .infinity, maxHeight: .infinity)
                                        .background(Color(#colorLiteral(red: 0.1351453364, green: 0.1446713805, blue: 0.2671209574, alpha: 1)))
                                    Text(items[index * 3 + 2])
                                        .frame(maxWidth: .infinity, maxHeight: .infinity)
                                        .background(Color(#colorLiteral(red: 0.9248386621, green: 0.3957888484, blue: 0.3508865833, alpha: 1)))
                                }
                                .frame(maxHeight: .infinity)
                                .frame(width: geometry.size.width * 1/3)
                            } else {
                                VStack(spacing: 0) {
                                    Text(items[index * 3])
                                        .frame(maxWidth: .infinity, maxHeight: .infinity)
                                        .background(Color(#colorLiteral(red: 0.1351453364, green: 0.1446713805, blue: 0.2671209574, alpha: 1)))
                                    Text(items[index * 3 + 1])
                                        .frame(maxWidth: .infinity, maxHeight: .infinity)
                                        .background(Color(#colorLiteral(red: 0.9248386621, green: 0.3957888484, blue: 0.3508865833, alpha: 1)))
                                }
                                .frame(maxHeight: .infinity)
                                .frame(width: geometry.size.width * 1/3)
                                Text(items[index * 3 + 2])
                                    .frame(maxHeight: .infinity)
                                    .frame(width: geometry.size.width * 2/3)
                                    .background(Color(#colorLiteral(red: 0.226172477, green: 0.3690122366, blue: 0.3273729682, alpha: 1)))
                            }
                        }
                        .frame(height: geometry.size.width * 6/16)
                    }
                }
            }
        }
        .foregroundColor(.white)
    }
}

Объяснение:

  • Строка с let items = ... - это просто быстрый способ сгенерировать список со строками от «Item 1» до «Item 12».
  • Рассмотрим каждую группу из трех элементов как «ряд». Тогда переменная range будет содержать количество строк.
  • Для каждой строки мы создаем HStack. Внутри него будет один большой элемент и два меньших в VStack. В четных строках (индекс% 2 == 0) VStack будет справа, в нечетных строках он будет слева.
  • Мы используем .frame(maxHeight: .infinity), чтобы элементы заполняли доступное место.
  • Но как получить нужный предмет в нужном месте? Как видите, я работал с index * 3, index * 3 + 1 и index * 3 + 2, где index - номер строки. Я проиллюстрирую это с помощью таблицы ниже:
    +-------------------------------------------+-------------------------------------------+-------------------------------------------+-------------------------------------------+
    | index = 0                                 | index = 1                                 | index = 2                                 | index = 3                                 |
    +-----------+---------------+---------------+-----------+---------------+---------------+-----------+---------------+---------------+-----------+---------------+---------------+
    | index * 3 | index * 3 + 1 | index * 3 + 2 | index * 3 | index * 3 + 1 | index * 3 + 2 | index * 3 | index * 3 + 1 | index * 3 + 2 | index * 3 | index * 3 + 1 | index * 3 + 2 |
    |    = 0    |      = 1      |      = 2      |    = 3    |      = 4      |      = 5      |    = 6    |      = 7      |      = 8      |    = 9    |      = 10     |      = 11     |
    +-----------+---------------+---------------+-----------+---------------+---------------+-----------+---------------+---------------+-----------+---------------+---------------+
    
...