I'm trying to create a 2x2 grid through either VStacks/HStacks or LazyVGrid to have the squares on each row fit the screen. For example, the first and second squares each take up half the width of the screen and based on that length, that'll determine the height to make it a square. How would I go about doing that in the two ways that I've mentioned or is there a better way to do it? Here's what I have so far.
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)
}
}
It feels wrong to hardcode the width and height for the frame property here or is that the way to go about removing the gaps between the squares? Would this way of hardcoding values scale to other phone sizes?
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)
}
EDIT: Here's what the new code looks like to get what I wanted.
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)
Now to get it working with LazyVGrid.
It feels wrong to hardcode the width and height for frame here or is that the way to go about removing the gaps between the squares?
To remove the gaps between the squares, just modify the HStack / VStack to include spacing:
HStack(alignment: .center, spacing: 0, content: {
Rectangle()
.fill(Color.gray)
.frame(width: 100, height: 100)
Rectangle()
.fill(Color.blue)
.frame(width: 100, height: 100)
})
You can use GeometryReader, as seen here.
Example usage:
struct MyView: View {
var body: some View {
GeometryReader { geo in
//You now have access to geo.size.width and geo.size.height
}
}
}
Just apply the aspectRatio (value 1 and fit the screen) modifier, there is no need to specify any frame.
VStack {
HStack {
Rectangle()
.fill(Color.gray)
Rectangle()
.fill(Color.blue)
}
HStack {
Rectangle()
.fill(Color.red)
Rectangle()
.fill(Color.green)
}
}
.aspectRatio(1.0, contentMode: .fit)
Related
Here is my code:
import SwiftUI
struct TrendingView : View {
#State var selectedTab: Tabs = .hot
#State private var searchText = ""
var body: some View {
NavigationView {
VStack {
HStack {
Text(" Trending")
.font(.largeTitle)
.frame(width: 175, height: 50, alignment: .leading)
.overlay(
RoundedRectangle(cornerRadius: 5)
.stroke(.black, lineWidth: 2)
)
.italic()
.fontWeight(.heavy)
.foregroundColor(Color(hue: 1.0, saturation: 0.977, brightness: 0.985))
.offset(x: -75, y: -25)
.padding(.bottom, -20)
NavigationLink(destination: testT()) {
Image(systemName: "magnifyingglass.circle.fill")
.resizable()
.scaledToFit()
.frame(width: 40, height: 40)
.foregroundColor(.black)
.padding(.bottom, -20)
}
.offset(x: 50, y: -25)
.padding(.leading, 5.0)
}
ScrollView {
VStack {
Text("Hot Items 🔥")
.bold()
.italic()
.offset(x: 5)
.frame(width: 120, height: 25, alignment: .leading)
.overlay(
RoundedRectangle(cornerRadius: 5)
.stroke(.black, lineWidth: 2)
)
.background(.yellow)
.offset(x: -130, y: 5)
ScrollView(.horizontal) {
HStack {
NavigationLink(destination: ImageTest()) {
Image("testpic1")
.resizable()
.frame(width: 200, height: 200)
}
NavigationLink(destination: ImageTest()) {
Image("testpic3")
.resizable()
.frame(width: 200, height: 200)
}
}.offset(y: 30)
}
}
}
There seems to be some error with scrollview above my vstack as it randomly causes all the content on this view to shift downwards when switching to and from other views.Ive tried removing the scrollview and the error disappears and also tried changing it around in other places but I still get the error Can anybody point me in the right direction? Thanks
Fixed, added to the bottom of my code and it seems like the issue is solved
.navigationBarTitle(Text(""), displayMode: .inline)
.navigationBarHidden(true)
Main View Code , My Subview CodeMy CardView is in ZStack and, when stretching the background image, didn't select in the right way a GridView in Main View here is my codes of main and subview
ScrollView {
NavigationLink("", destination: CardCategoryView(cardCategoryVm: .init(card: cardsVm.selectedCard)), isActive: $cardsVm.isShowingCardCategory)
LazyVGrid(columns: gridColoumns,spacing: 8) {
ForEach(cardsVm.cards?.vendor ?? [] ,id: \.self) { symbol in
StoreCardView(image: symbol.image ?? "")
.frame(width: UIScreen.main.bounds.width / 2 - 20,height: UIScreen.main.bounds.width / 2 - 20)
.padding(.top)
.onTapGesture {
let _ = print(symbol.name)
cardsVm.selectedCard = symbol
cardsVm.isShowingCardCategory = true
}
}
}
}
struct StoreCardView: View {
var image:String
var body: some View {
GeometryReader { reader in
ZStack{
KFImage(URL(string:image))
.resizable()
.scaleEffect(x: 3, y: 3, anchor: .center)
.aspectRatio(contentMode: .fit)
.frame(width: reader.size.width , height: reader.size.height , alignment: .center)
.clipped()
.blur(radius: 25, opaque: true)
.opacity(0.7)
.cornerRadius(8)
KFImage(URL(string:image))
.resizable()
.aspectRatio( contentMode: .fill)
.frame(width: reader.size.width/2, height: reader.size.height/2, alignment: .center)
.clipShape(Circle())
.shadow(color: .movColor.opacity(0.4),radius: 5,
x: 0,
y: 0
)
//
} .fixedSize(horizontal: true, vertical: true)
.frame(width: reader.size.width, height: reader.size.height, alignment: .center)
.clipped()
}
}
}
I made it in Ztack and gave it a fixed frame with Scale Effect and it didn't work also, how can I make the background image stretching and didn't effect on gridview at main view
I'm having some trouble understanding how to properly align items in top of each other:
So I have the following VStack:
VStack(spacing: 0) {
Text("\(placeC.places.count)")
Image("map-pin-full-cluster-1")
.renderingMode(.template)
.resizable()
.frame(width: 35, height: 35)
.foregroundColor(.brown)
} //: END VStack
Which produces the following output:
What is the best way to have the number inside the circle? Is there a recommended SwiftUI builder that you all use that I can explore?
Typically you would use an .overlay:
Image("map-pin-full-cluster-1")
.renderingMode(.template)
.resizable()
.frame(width: 35, height: 35)
.foregroundColor(.brown)
.overlay(alignment: .top) {
Text("\(placeC.places.count)")
}
or a ZStack:
ZStack(alignment: .top) { // other alignments: .center, .bottom, .leading, .trailing
Image("map-pin-full-cluster-1")
.renderingMode(.template)
.resizable()
.frame(width: 35, height: 35)
.foregroundColor(.brown)
Text("\(placeC.places.count)")
.padding(.top, 4) // adjust this to move the text up/down
}
When I drag the rectangle to the left, the symbol is under the rectangle but on the right the symbol is over the rectangle, when I drag it to the right. I know, that the hierarchy of the HStack decides the layer but if I would do the right symbol over the rectangle, then both of the symbols are on the right side. I'm new at SwiftUI
HStack(spacing: 0.0){
Image(systemName: "lessthan.square")
.resizable()
.frame(width: 20.0, height: 20.0)
.padding(.leading, 30.0)
ZStack(alignment: .center) {
Group {
Rectangle()
.cornerRadius(20.0)
.frame(width: 250, height: 150)
.foregroundColor(Color(.white))
.position(rectPosition)
.shadow(radius: 5)
VStack{
Text("i")
.font(.system(size: 30))
Text("l")
.font(.system(size: 25))
}.position(rectPosition)
}.gesture(DragGesture().onChanged({ value in
self.rectPosition = CGPoint(x: value.location.x, y: 130)
}))
}
Image(systemName: "greaterthan.square")
.resizable()
.frame(width: 20.0, height: 20.0)
.padding(.trailing, 30.0)```
zIndex should help you... add it to ZStack
HStack {
Image(...)
ZStack {
...
}.zIndex(1) // << here !!
Image(...)
}
I try to put a circle-shaped frame around a text view, but I just can't get it properly aligned and I can't see where the problem is. As you can see in the picture below, the text is sometimes offset to left, while it should be centred. Any ideas on how to fix it?
struct ContentView: View {
let result = getDate();
var body: some View {
VStack {
ScrollView(.horizontal, showsIndicators: false) {
HStack(alignment: .top, spacing: 5) {
ForEach(result, id: \.self) {
day in
Text(day.name!)
.frame(width: 35, height: 35, alignment: .center)
.padding()
.overlay(
Circle()
.size(width: 35, height: 35)
.offset(x: 17.5,y: 17.5)
.scale(1.4)
.stroke(Color.orange, lineWidth: 4)
)
}
}
}
Spacer()
}.background(Color.white)
}
}
The circle is offset by half of the size of the frame, so its origin should be in the centre. The Text should be centered as well in .frame(width: 35, height: 35, alignment: .center).
Thanks a lot for helping! :)
.overlay already has size of container with Text an Circle centred in it, so it is just needed to operate with insets of circle not shifting it, like below
Text(day.name!)
.frame(width: 35, height: 35, alignment: .center)
.padding()
.overlay(
Circle()
.stroke(Color.orange, lineWidth: 4)
.padding(6)
)