I am trying to create a view that is a rectangle with text and images inside. This is done in a VStack. At the bottom of the VStack, I have an HStack where I have a small image and a number next to it. These need to be centred aligned but I can't seem to make that happen.
The image is higher up than the number. I need them to be at an equal height.
VStack(alignment: .center, spacing: 0) {
Image("ProductLogo")
.resizable()
.aspectRatio(contentMode: .fit)
.clipped()
.padding()
.layoutPriority(1)
Text("Text Here")
.font(.title2)
.fontWeight(.bold)
.foregroundColor(.black)
.minimumScaleFactor(0.5)
.multilineTextAlignment(.center)
.padding(.leading, 5)
.padding(.trailing, 5)
.padding(.bottom, 5)
Text("Subtitle")
.font(.headline)
.foregroundColor(.gray)
.lineLimit(2)
.padding(1)
//HERE IS WHAT NEEDS TO BE ALIGNED
HStack {
Image("CoinImage")
.resizable()
.frame(width: 35, height: 35, alignment: .center)
Text("500")
.font(.system(size: 20))
.padding(.top,20)
}
//END OF HSTACK
}
Here is an image of the VStack:
The 500 should be level with the coin image
You just need to remove padding from Text("500") and set to HStack
Please try with below code and let me know it's works for you
VStack(alignment: .center, spacing: 0) {
Image("ProductLogo")
.resizable()
.aspectRatio(contentMode: .fit)
.clipped()
.padding()
.layoutPriority(1)
Text("Text Here")
.font(.title2)
.fontWeight(.bold)
.foregroundColor(.black)
.minimumScaleFactor(0.5)
.multilineTextAlignment(.center)
.padding(.leading, 5)
.padding(.trailing, 5)
.padding(.bottom, 5)
Text("Subtitle")
.font(.headline)
.foregroundColor(.gray)
.lineLimit(2)
.padding(1)
//HERE IS WHAT NEEDS TO BE ALIGNED
HStack {
Image("CoinImage")
.resizable()
.frame(width: 35, height: 35, alignment: .center)
Text("500")
.font(.system(size: 20))
}.padding(.top, 10)
//END OF HSTACK
}
Related
I am creating a view that is a rectangle that contains an: image, name, subtitle.
I have these in a VStack with a frame. In this VStack, the views stack correctly. However, I want the subtitle (which is text) to always be stuck to the bottom of the VStack.
At the moment the subtitle is pushed up with the other views. I tried using Spacer's but these didn't seem to do the job (maybe I used them wrong???).
Here is the view:
VStack(alignment: .center, spacing: 0) {
Image("Image")
.resizable()
.aspectRatio(contentMode: .fit)
.clipped()
.padding()
.layoutPriority(1)
}
}
Text("Name")
.font(.title2)
.fontWeight(.bold)
.foregroundColor(.black)
.minimumScaleFactor(0.5)
.multilineTextAlignment(.center)
.padding(.leading, 5)
.padding(.trailing, 5)
.padding(.bottom, 5)
Text("Subtitle")
.font(.caption)
.foregroundColor(.gray)
.lineLimit(2)
.padding(1)
}
.frame(width: 150, height: 200)
Any ideas?
Put the subtitle into an .overlay() of the VStack and use alignment: .bottom to push it to the bottom:
VStack(alignment: .center, spacing: 0) {
Image("Image")
.resizable()
.aspectRatio(contentMode: .fit)
.clipped()
.padding()
.layoutPriority(1)
Text("Name")
.font(.title2)
.fontWeight(.bold)
.foregroundColor(.black)
.minimumScaleFactor(0.5)
.multilineTextAlignment(.center)
.padding(.leading, 5)
.padding(.trailing, 5)
.padding(.bottom, 5)
}
.frame(width: 150, height: 200)
.overlay(alignment: .bottom) {
Text("Subtitle")
.font(.caption)
.foregroundColor(.gray)
.lineLimit(2)
.padding(1)
}
Disclaimer: New to SwiftUI
I know a ZStack() view allows me to overlap views, which is what I want for the heading section of the app.
I set the ZStack() to not take up the entire height and had expected an HStack(), placed after the ZStack() to do just that, appear after. Instead it also overlaps with the ZStack.
I'm sure it's a simple solution to co-exist. Image and code below.
var body: some View {
GeometryReader { geometry in
ZStack(alignment: .topLeading) {
Ellipse()
.fill(self.bgColor)
.frame(width: geometry.size.width * 1.4, height: geometry.size.height * 0.28)
.position(x: geometry.size.width / 2.35, y: geometry.size.height * 0.1)
.shadow(radius: 3)
.edgesIgnoringSafeArea(.all)
HStack(alignment: .top) {
VStack(alignment: .leading) {
Text(self.title)
.font(.title)
.fontWeight(.bold)
.foregroundColor(Color.white)
Text(self.subtitle)
.font(.subheadline)
.fontWeight(.regular)
.foregroundColor(Color.white)
}
.padding(.leading, 25)
.padding(.top, 20)
Spacer()
VStack(alignment: .trailing) {
Image("SettingsIcon")
.resizable()
.scaledToFit()
.frame(width: 30, height: 30)
}
.padding(.top, 20)
.padding(.trailing, 25)
}
}
.fixedSize(horizontal: false, vertical: true)
HStack(alignment: .top) {
Text(self.title)
.font(.title)
.fontWeight(.bold)
.foregroundColor(Color.white)
}
}
}
Try the following code using a top VStack and closing the GeometryReader before the last HStack:
var body: some View {
VStack { // <-- here
GeometryReader { geometry in
ZStack(alignment: .topLeading) {
Ellipse()
.fill(self.bgColor)
.frame(width: geometry.size.width * 1.4, height: geometry.size.height * 0.28)
.position(x: geometry.size.width / 2.35, y: geometry.size.height * 0.1)
.shadow(radius: 3)
.edgesIgnoringSafeArea(.all)
HStack(alignment: .top) {
VStack(alignment: .leading) {
Text(self.title)
.font(.title)
.fontWeight(.bold)
.foregroundColor(Color.white)
Text(self.subtitle)
.font(.subheadline)
.fontWeight(.regular)
.foregroundColor(Color.white)
}
.padding(.leading, 25)
.padding(.top, 20)
Spacer()
VStack(alignment: .trailing) {
Image("SettingsIcon")
.resizable()
.scaledToFit()
.frame(width: 30, height: 30)
}
.padding(.top, 20)
.padding(.trailing, 25)
}
}.fixedSize(horizontal: false, vertical: true)
} // <-- here end GeometryReader
HStack(alignment: .top) {
Text(self.title)
.font(.title)
.fontWeight(.bold)
.foregroundColor(Color.white)
}
} // <-- here end VStack
}
I'm creating an iOS minesweeper game and want to have a bar at the top with three pieces of information:
The high score (next to a trophy symbol) [LEFT]
The current time (next to a timer symbol) [CENTER]
The number of bombs left (next to a bomb symbol) [RIGHT]
However, the elements are not evenly aligned as you can see in the picture at the bottom- I'm guessing the spacers are automatically the same size. So, because the text on the left side of the screen is wider than that on the right, the middle text is offset to the right.
How can I align these items so the center time/image is perfectly in the middle with the other objects on the left/right?
My code looks like:
struct GameView: View {
#EnvironmentObject var game: Game
#State var labelHeight = CGFloat.zero
var body: some View {
VStack(alignment: .center, spacing: 10) {
Text("MINESWEEPER")
.font(.system(size: 25, weight: .bold, design: .monospaced))
.kerning(3)
.foregroundColor(.red)
HStack(alignment: .center, spacing: 5) {
Image(systemName: "rosette")
.resizable()
.aspectRatio(contentMode: .fit)
.foregroundColor(.black)
Text(game.highScoreString)
.font(.system(size: 15, weight: .bold, design: .monospaced))
.foregroundColor(.black)
Spacer()
Image(systemName: "timer")
.resizable()
.aspectRatio(contentMode: .fit)
.foregroundColor(.black)
Text(game.timerString)
.font(.system(size: 15, weight: .bold, design: .monospaced))
.foregroundColor(.black)
Spacer()
Image("top_bomb")
.resizable()
.aspectRatio(contentMode: .fit)
Text(String(game.bombsRemaining))
.font(.system(size: 15, weight: .bold, design: .monospaced))
.foregroundColor(.black)
.overlay(GeometryReader(content: { geometry in
Color.clear
.onAppear(perform: {self.labelHeight = geometry.frame(in: .local).size.height})
}))
}
.frame(width: UIScreen.main.bounds.width * 0.9, height: labelHeight, alignment: .center)
BoardView()
}
}
}
Instead of aligning by spacers, move each part into separate view, say LeftHeader, CenterHeader, and RightHeader and use frame alignment, which gives exact separation by equal sizes, like
HStack {
LeftHeader()
.frame(maxWidth: .infinity, alignment: .leading)
CenterHeader()
.frame(maxWidth: .infinity, alignment: .center)
RightHeader()
.frame(maxWidth: .infinity, alignment: .trailing)
}
This can be achieved using a ZStack , HStack and Spacers.
ZStack{
HStack{
Text("Left")
Spacer()
}
HStack{
Text("Center")
}
HStack{
Spacer()
Text("Right")
}
}
Even if you remove left ( or right ) HStack, it won't affect the other components or the layout.
You can make it look bit nicer by adding paddings like this,
ZStack{
HStack{
Text("Left").padding([.leading])
Spacer()
}
HStack{
Text("Center")
}
HStack{
Spacer()
Text("Right").padding([.trailing])
}
}
I think you can create more one stack.
My solution like:
/**
* spacing is an example
* minWidth calculated by fontSize
*/
HStack(alignment: .center, spacing: 20){
HStack{ Image, Text }.frame(minWidth: 30)
HStack{ Image, Text }.frame(minWidth: 30)
HStack{ Image, Text }.frame(minWidth: 30)
}
Hope it useful for you.
i'm somewhat new to working with JSON data in Swift so I have a problem with it.
I did fetch all the vars from JSON into SwiftUI, working really well, except I don't know how to decode videos from JSON and add them to SwiftUI
From what I see in the JSON there is a Video Endpoint
( ex. base]/uploads/companymedia/[id]/[value].mp4", )
But, im not sure how to decode it, and put it so it works in my SwiftUI file. Currently its fetching everything ( text, subtext, images ) just not videos and on the part where the video should be it just shows an image.
The code is this:
HStack{
Text(post.title)
.font(.system(size: 18))
.fontWeight(.heavy)
.foregroundColor(Color(.label))
Spacer()
Button(action: shareButton){
Image(systemName: "square.and.arrow.up")
.font(.system(size: 22))
.foregroundColor(Color.gray)
.padding(.top, 15)
.padding(.bottom, 20)
.padding(.horizontal, 15)
}
}
if let text = post.text{
Text(text)
.lineLimit(2)
.foregroundColor(Color(.label).opacity(0.5))
}
Text(dateFormatter.string(from: post.date))
.font(.system(size: 14))
.foregroundColor(Color(.label).opacity(0.5))
}
.padding(16)
GeometryReader{ geometry in
PagedScrollView(numberOfPages: post.images.count){
HStack(spacing: 0){
ForEach(post.images, id: \.self){ image in
KFImage(URL(string: image)!)
.setProcessor(processor)
.cacheOriginalImage(true)
.backgroundDecode(true)
.loadImmediately()
.fade(duration: 1)
.placeholder({
Color.red
})
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: geometry.size.width, height: geometry.size.height)
.clipped()
}
}
}
.frame(width: geometry.size.width, height: geometry.size.height)
.tabViewStyle(PageTabViewStyle())
.indexViewStyle(PageIndexViewStyle(backgroundDisplayMode: .always))
}
.frame(height: 400)
HStack{
Locallike(isLiked: $isLiked)
.padding(.horizontal, 10)
.padding(.top,15)
.padding(.bottom, 20)
SmileLike(isSmiled: $isSmiled)
.font(.system(size: 22))
.padding(.top, 15)
.padding(.bottom, 20)
.padding(.horizontal,15)
Spacer()
NavigationLink(destination: CommentsView(postId: post.id)) {
Image(systemName: "message")
.font(.system(size: 22))
.foregroundColor(Color.gray)
.padding(.top, 15)
.padding(.bottom, 20)
.padding(.horizontal,15)
}
}
}
.background(Color(.label).opacity(0.1))
.cornerRadius(8)
}
```
I'm working on a proof of concept app in SwiftUI and I came up with an idea for a settings pane looking like this:
Now I want the user to be able to tap the colored "Option X" to change the text. I thought I'd just replace Text() with TextField() but if I do this it produces a view like this:
Here is the code I'm using for the view:
HStack(){
Spacer()
ZStack{
Rectangle()
.fill(Color(txtBgCol!))
.frame(width: 300, height: 475)
.cornerRadius(25)
.shadow(radius: 3)
VStack{
Group{
Spacer()
// preset 1
TextField(presets[0].name, text: $presets[0].name)
//Text(presets[0].name)
.foregroundColor(.white)
.padding()
.background(presets[0].color)
.cornerRadius(200)
.shadow(radius: 3)
.font(.body)
Text("Some settings here")
.foregroundColor(Color(txtCol!))
.padding()
.font(.body)
}
Group{
Spacer()
// preset 2
Text(presets[1].name)
.foregroundColor(.white)
.padding()
.background(presets[1].color)
.cornerRadius(200)
.shadow(radius: 3)
.font(.body)
Text("Some settings here")
.foregroundColor(Color(txtCol!))
.padding()
.font(.body)
}
Group{
Spacer()
// preset 3
Text(presets[2].name)
.foregroundColor(.white)
.padding()
.background(presets[2].color)
.cornerRadius(200)
.shadow(radius: 3)
.font(.body)
Text("Some settings here")
.foregroundColor(Color(txtCol!))
.padding()
.font(.body)
}
Spacer()
}
}
Spacer().frame(width: 30)
}
I'm not sure why changing the Text() to TextField() would mess up everything and I'd be glad to learn more about SwiftUI intricacies, as I am pretty new to this.
TextField by default expands to max available width, so instead of limit only background rectangle, you should limit container
ZStack{
Rectangle()
.fill(Color(txtBgCol!))
.frame(width: 300, height: 475)
.cornerRadius(25)
.shadow(radius: 3)
VStack{
// .. other code here
}
.frame(width: 300, height: 475) // << this restricts TextField expanding