One more thing, since you are using almost the same set of modifiers on every view, create your own ViewModifier and use that instead. I have made one for you as an example.
struct cardModifier: ViewModifier {
var fontSize, frameWidth, frameHeight: CGFloat
var frameAlignment: Alignment
var backgroundColour: Color
var backgroundColourOpacity: Double
var shadowRadius: CGFloat
var foregroundColour: Color
var foregroundColourOpacity: Double?
var cardText: String
var overlayFontSize: CGFloat
func body(content: Content) -> some View {
content
.font(.system(size: fontSize))
.padding()
.frame(width: frameWidth, height: frameHeight, alignment: frameAlignment)
.background(Rectangle().fill(backgroundColour .opacity(backgroundColourOpacity)) .shadow(radius: shadowRadius))
.cornerRadius(20)
.foregroundColor(foregroundColour.opacity(foregroundColourOpacity ?? 1))
.overlay(Text(cardText).foregroundColor(.black).padding() .font(.system(size: overlayFontSize)), alignment: .bottom)
}
}
extension View {
func cardStyle(fontSize: CGFloat, frameWidth: CGFloat, frameHeight: CGFloat, frameAlignment: Alignment, backgroundColour: Color, backgroundColourOpacity: Double, shadowRadius: CGFloat, foregroundColour: Color, foregroundColourOpacity: Double? = 1, cardText: String, overlayFontSize: CGFloat) -> some View {
modifier(cardModifier(fontSize: fontSize,
frameWidth: frameWidth,
frameHeight: frameHeight, frameAlignment: frameAlignment,
backgroundColour: backgroundColour,
backgroundColourOpacity: backgroundColourOpacity,
shadowRadius: shadowRadius,
foregroundColour: foregroundColour,
cardText: cardText,
overlayFontSize: overlayFontSize))
}
}
I had to make this a separate post as I ran out of characters in the first one.
Post
Replies
Boosts
Views
Activity
Hi,
I saw your question a few hours ago and I don't know if you are still looking for an answer at this time. Anyways, here is the solution with an explanation for anyone who might be interested in it.
You have a LazyVGrid with two columns which is what you are seeing in the screenshot you've provided. UnitView(), TemperatureView() and CurrencyView() form the first column, whereas DistanceView() and TimeView() form the second column. Since you did not specify the alignment property, it assumed its default value, which is HorizontalAlignment.center in the case of LazyVGrid.
If you specify alignment as HorizontalAlignment.leading, then the view would look somewhat like how you want it to look.
But, it doesn't look good because the cards are not in the middle of the screen. To solve this, you would have to embed LazyVGrid into a LazyVStack, take the CurrencyView() out of the LazyVGrid, and place it outside LazyVGrid but within LazyVStack.
struct ContentView: View {
let columns = [ GridItem(.fixed(150), spacing: 30), GridItem(.fixed(150), spacing: 30)]
var body: some View {
NavigationView{
LazyVStack {
LazyVGrid(columns: columns) {
NavigationLink(destination: UnitView()) {
Image(systemName: "scalemass")
.cardStyle(fontSize: 60,
frameWidth: 150,
frameHeight: 150,
frameAlignment: .center,
backgroundColour: .purple,
backgroundColourOpacity: 0.5,
shadowRadius: 3,
foregroundColour: .black,
cardText: "Weight",
overlayFontSize: 22)
}
NavigationLink(destination: DistanceView()) {
Image(systemName: "figure.walk")
.cardStyle(fontSize: 60,
frameWidth: 150,
frameHeight: 150,
frameAlignment: .center,
backgroundColour: .orange,
backgroundColourOpacity: 0.5,
shadowRadius: 3,
foregroundColour: .black,
cardText: "Distance",
overlayFontSize: 22)
}
NavigationLink(destination: TemperatureView()) {
Image(systemName: "thermometer.sun")
.cardStyle(fontSize: 56,
frameWidth: 150,
frameHeight: 150,
frameAlignment: .center,
backgroundColour: .yellow,
backgroundColourOpacity: 0.5,
shadowRadius: 3,
foregroundColour: .black,
cardText: "Temperature",
overlayFontSize: 21)
}
NavigationLink(destination: TimeView()) {
Image(systemName: "clock")
.cardStyle(fontSize: 60,
frameWidth: 150,
frameHeight: 150,
frameAlignment: .center,
backgroundColour: .blue,
backgroundColourOpacity: 0.5,
shadowRadius: 3,
foregroundColour: .black,
cardText: "Time",
overlayFontSize: 21)
}
}
NavigationLink(destination: CurrencyView()) {
Image(systemName: "dollarsign.square.fill")
.cardStyle(fontSize: 90,
frameWidth: 330,
frameHeight: 150,
frameAlignment: .top,
backgroundColour: .green,
backgroundColourOpacity: 0.4,
shadowRadius: 10,
foregroundColour: .white,
cardText: "Currency Converter",
overlayFontSize: 27)
}
}
}
}
}
Notice that the CurrencyView() is not in the LazyVGrid anymore. So, it is not in the first column.
Now it looks exactly like you wanted.
I hope this helps you!
Thank you!