Как сделать так, чтобы квадрат 2x2 поместился на экран в SwiftUI

Я пытаюсь создать сетку 2x2 через VStacks / HStacks или LazyVGrid, чтобы квадраты в каждой строке соответствовали экрану. Например, первый и второй квадраты занимают половину ширины экрана, и на основе этой длины будет определяться высота, чтобы сделать его квадратом. Как бы я сделал это двумя упомянутыми мною способами или есть лучший способ сделать это? Вот что у меня есть на данный момент.

VStack {
    HStack {
        Rectangle()
            .fill(Color.gray)
            .frame(width: 100, height: 100)

        Rectangle()
            .fill(Color.blue)
            .frame(width: 100, height: 100)
    }
    HStack {
        Rectangle()
            .fill(Color.red)
            .frame(width: 100, height: 100)

        Rectangle()
            .fill(Color.green)
            .frame(width: 100, height: 100)
    }
}

Стеки

Кажется неправильным жестко задавать ширину и высоту для свойства frame или это способ удалить зазоры между квадратами? Будет ли этот способ жесткого кодирования масштабироваться для других размеров телефона?

LazyVGrid(columns: layout) {
    Rectangle()
        .fill(Color.gray)
        .frame(width: 210, height: 210)
    Rectangle()
        .fill(Color.blue)
        .frame(width: 210, height: 210)
    Rectangle()
        .fill(Color.red)
        .frame(width: 210, height: 210)
    Rectangle()
        .fill(Color.green)
        .frame(width: 210, height: 210)
}

LazyVGrid

РЕДАКТИРОВАТЬ: Вот как выглядит новый код, чтобы получить то, что я хотел.

VStack(spacing: 0) {
    HStack(spacing: 0) {
        Rectangle()
            .fill(Color.gray)

        Rectangle()
            .fill(Color.blue)

    }
    HStack(spacing: 0) {
        Rectangle()
            .fill(Color.red)

        Rectangle()
            .fill(Color.green)

    }
}
.aspectRatio(1.0, contentMode: .fit)

введите описание изображения здесь

Теперь, чтобы заставить его работать с LazyVGrid.


person Petesta    schedule 18.05.2021    source источник
comment
Вы можете использовать UIScreen.main.bounds.width, если вы поддерживаете только портретный режим   -  person SwiftiSwift    schedule 18.05.2021
comment
@SwiftiSwift, это полезно знать. Я этого не знал.   -  person Petesta    schedule 18.05.2021


Ответы (3)


Просто примените модификатор aspectRatio (значение 1 и размер экрана), нет необходимости указывать какой-либо фрейм.

VStack {
    HStack {
        Rectangle()
            .fill(Color.gray)
            
        Rectangle()
            .fill(Color.blue)
            
    }
    HStack {
        Rectangle()
            .fill(Color.red)
        
        Rectangle()
            .fill(Color.green)
            
    }
}
.aspectRatio(1.0, contentMode: .fit)
person vadian    schedule 18.05.2021
comment
Никакого значения не требуется. ContentMode достаточно .aspectRatio(contentMode: .fit) - person Leo Dabus; 18.05.2021
comment
@Leo Я знаю, значение проясняет OP - person vadian; 18.05.2021
comment
@vadian спасибо. Это помогло. Осталось добавить spacing: 0 в VStack и два HStack. - person Petesta; 18.05.2021

Вы можете использовать GeometryReader, как показано здесь.

Пример использования:

struct MyView: View {
    var body: some View {
       GeometryReader { geo in
           //You now have access to geo.size.width and geo.size.height
       }
    }
}
person West1    schedule 18.05.2021
comment
Это должен быть правильный ответ - person SwiftiSwift; 18.05.2021
comment
@SwiftiSwift почему? Нет необходимости запрашивать размер экрана - person Leo Dabus; 18.05.2021

Кажется неправильным жестко задавать здесь ширину и высоту рамки, или это способ удалить зазоры между квадратами?

Чтобы удалить промежутки между квадратами, просто измените HStack / VStack, включив интервал:

HStack(alignment: .center, spacing: 0, content: {
            Rectangle()
                .fill(Color.gray)
                .frame(width: 100, height: 100)

            Rectangle()
                .fill(Color.blue)
                .frame(width: 100, height: 100)
})
person jp21    schedule 18.05.2021