I'm trying to build the subscription price info boxes like the screenshot below. How can I achieve these boxes to be square and take up the full width of the screen (minus spacing)
(Just to be clear, I'm interested in how two boxes can be square and take their height values from screen size automatically. I'm not interested in full design as it will be handled after achieving the box sizes) So far what I tried is like below:
This is for individual boxes:
struct SubscriptionPriceBox: View {
let title: String
let duration: String
let price: String
let renewInfo: String
var body: some View {
ZStack(alignment: .top) {
VStack {
VStack {
Text(duration)
Text(price)
}
Text(renewInfo)
}
.overlay {
RoundedRectangle(cornerRadius: 2)
.stroke(.gray, lineWidth: 2)
}
.aspectRatio(1, contentMode: .fit)
.frame(maxWidth: .infinity)
Text(title)
.background(Color.yellow)
.offset(x: -20, y: -10)
}
.background(Color.red)
}
And this code is the container view for them:
var body: some View {
VStack {
HStack(alignment: .center) {
SubscriptionPriceBox(title: "Basic Price",
duration: "Monthly",
price: "2.49$ / month",
renewInfo: "Renew every month")
SubscriptionPriceBox(title: "Save 33%",
duration: "Annual",
price: "19.99$ / month",
renewInfo: "Renew every year")
}.fixedSize(horizontal: true, vertical: false)
I think using GeometryReader is one option but couldn't figure that out completely. Also if there is a way to achieve this without using GeometryReader, I'm curious to learn it.
CodePudding user response:
You were close, you can use a LazyVGrid
to make sure the view is always 2 columns then use the GeometryReader
to match the sizes
import SwiftUI
struct boxProblem: View {
private let gridItemLayout = Array(repeating: GridItem(.flexible(), spacing: 10), count: 2)
var body: some View {
VStack {
LazyVGrid(columns: gridItemLayout) {
SubscriptionPriceBox(title: "Basic Price",
duration: "Monthly",
price: "2.49$ / month",
renewInfo: "Renew every month")
SubscriptionPriceBox(title: "Save 33%",
duration: "Annual",
price: "19.99$ / month",
renewInfo: "Renew every year")
}
.padding(.horizontal)
}
}
}
struct SubscriptionPriceBox: View {
let title: String
let duration: String
let price: String
let renewInfo: String
var body: some View {
GeometryReader { geometry in
ZStack(alignment: .topLeading) {
VStack {
VStack {
Text(duration)
Text(price)
}
Text(renewInfo)
}
.frame(maxWidth: .infinity)
.frame(height: geometry.size.width)
.overlay {
RoundedRectangle(cornerRadius: 2)
.stroke(.gray, lineWidth: 2)
}
Text(title)
.background(Color.yellow)
.offset(x: -20, y: -10)
}
.background(Color.red)
}
}
}