enter image description here
Hi, I'm trying to make the ui like in the picture above, but I'm failing at it right now, I would like to have the text under "German" as a list with a maximum of 3 items, the text should also be arranged evenly, I've been trying to do it for a while, but unfortunately I'm not that familiar with SwiftUi yet :)
HStack{
Group{
VStack{
HStack{
Text("Deutsch:")
.font(Font.custom("Jua-Regular", size: 22))
.padding(12.0)
}
VStack{
Spacer()
Text("- Lesen")
.font(Font.custom("Jua-Regular", size: 18))
Spacer()
Text("- Ab beende")
.font(Font.custom("Jua-Regular", size: 18))
Spacer()
Text("- Gedicht lernen")
.font(Font.custom("Jua-Regular", size: 18))
Spacer()
}
}
}
.background(Color(red: 0.6039215686274509, green: 0.788235294117647, blue: 0.8901960784313725))
.cornerRadius(12)
.padding(22)
Spacer()
Group{
VStack{
HStack{
Text("Musik")
.font(Font.custom("Jua-Regular", size: 22))
.padding(12.0)
}
VStack{
Spacer()
Text("- Singen")
.font(Font.custom("Jua-Regular", size: 18))
Spacer()
Text("- Vortrag")
.font(Font.custom("Jua-Regular", size: 18))
Spacer()
Text("- Mozart lernen Lebenslauf!")
.font(Font.custom("Jua-Regular", size: 18))
Spacer()
}
}
}
.background(Color(red: 0.6039215686274509, green: 0.788235294117647, blue: 0.8901960784313725))
.cornerRadius(12)
.padding(22)
Spacer()
}
}
You can't. If you are doing the UI static, this should be static. Exactly like you wrote. This is probably a Proof of Concept, in this case you should have a ViewController managing the data. So put the data into a List and call sorted() on the List. Before pass to the view. If you have no idea what I'm talking about look for MVVM, there are good materials out there simple enough to understand and follow. In the Apple's website (developer.apple.com) there is a MVVM/SwiftUI example App. Keep in mind that Apple's examples and codes are ALWAYS a little bit behind, so you may have to start with the provided code or keep attention to what target you should be using. Probably iOS 14.0.
Related
Given the following code snippet, I can align the leading edges of the text views but how can I specify that I want them to be aligned with their leading edges yet a certain number of pixels from the left edge of the actual VStack container?
VStack {
Text("Simple Swift Guide")
.font(.title)
Text("SwiftUI Tutorials")
.font(.subheadline)
.foregroundColor(.gray)
}
.frame(maxWidth: .infinity)
.background(Color.yellow)
Here is possible approach for your snippet (if I understood your goal correctly) - alignment is external so internal VStack content can be any.
VStack(alignment: .leading) {
Text("Simple Swift Guide")
.font(.title)
Text("SwiftUI Tutorials")
.font(.subheadline)
.foregroundColor(.gray)
}
.frame(maxWidth: .infinity, alignment: .leading)
.padding(.leading, 25)
.background(Color.yellow)
I can't seem to get the Spacer() function to work when I'm within an HStack and trying to create space between my Text and Textfield views. The Spacer works to space out other areas of the view, but whenever I attempt to space between these two elements, it doesn't work.
Here is the code I'm working with:
VStack(alignment: .leading, spacing: 0) {
Rectangle()
.frame(height: 2, alignment: .top)
.foregroundColor(Color("grey2"))
Text("Tickets")
.kerning(0.5)
.scaledFont(name: "Gotham Medium", size: 18)
.foregroundColor(Color("grey4"))
.padding(.horizontal)
.padding(.bottom, 3)
.padding(.top, 35)
Rectangle()
.frame(height: 2, alignment: .top)
.foregroundColor(Color("grey2"))
HStack {
Text("Ticket URL")
.kerning(0.5)
.scaledFont(name: "Gotham Book", size: 16)
.foregroundColor(Color("spaceblack"))
Spacer()
TextField("Enter URL", text: $url)
}
.background(Color.blue)
.padding()
Rectangle()
.frame(height: 2, alignment: .top)
.foregroundColor(Color("grey2"))
}
.frame(maxWidth: .infinity)
.background(Color.red)
try adding .fixedSize() modifier to your TextField
TextField("Enter URL", text: $url)
.fixedSize()
or set a frame like so
TextField("Enter URL", text: $url)
.frame(width:200, height:50, alignment:.leading)
The problem is that TextField and Spacer() would take all available space and in this case TextField gets the priority; However, if you specify a fixed size or a frame to it then TextField won't stretch to take full space instead it will be fixed.
.fixedSize would allow your TextField to start small but eventually it will keep stretching the more text you write which can cause unwanted behavior.
.frame will fix your size to the provided width and hence there won't be any stretch and Spacer will have priority to take available space.
Im using .edgesIgnoringSafeArea(.top) to ignore the safe area on the top. this seems to work, and show the image going over the safe area on the top as expected on the canvas. But when I run this on a iPhone 11 plus simulator or iPhone x device (i also tested on other devices on the simulator) it doesn't seem to ignore the edges.
I have tried excluding:
.navigationBarTitle("")
.navigationBarBackButtonHidden(true)
But I need the above so I can use a custom back button.
var body: some View {
VStack (alignment: .leading ) {
Image("user1")
.resizable()
.frame(width: (UIScreen.main.bounds.width), height: ((UIScreen.main.bounds.height) / 2) + 50)
ScrollView {
HStack {
Text("\(userData.username), 30")
.fontWeight(.semibold)
.font(.system(.largeTitle, design: .rounded))
.padding([.leading,.top])
Spacer()
Image(systemName: "paperplane")
.aspectRatio(contentMode: .fill)
.frame(width: 65, height: 65)
.background(Color("message-background"))
.foregroundColor(.white)
.cornerRadius(25)
.font(.system(size: 25))
.padding(.top)
}.padding(.trailing)
HStack {
Text("Singer, London")
.fontWeight(.light)
.padding([.leading])
Spacer()
}
HStack {
Text("all the bio info will go there all the bio info will go thereall the bio info will go thereall the bio info will go there all the bio info will go there.")
.fontWeight(.light)
.padding([.leading])
.padding(.top)
.frame(width: (UIScreen.main.bounds.width - 20))
Spacer()
}.padding(.bottom,50)
}
}.edgesIgnoringSafeArea(.top)
.navigationBarTitle("")
.navigationBarBackButtonHidden(true)
.navigationBarItems(leading: Button(action: {
self.presentationMode.wrappedValue.dismiss()
}){
Image(systemName: "arrow.left")
.aspectRatio(contentMode: .fill)
.frame(width: 40, height: 40)
.background(Color("message-background"))
.foregroundColor(.white)
.cornerRadius(15)
.font(.system(size: 15))
.padding(.top,20)
})
}
Your code works for me on the simulator as expected. I just added the Text "This works" to demonstrate it:
So your problem must be somewhere outside the code which you presented in your question.
i have an image that i want to strech only it's height to fit different content, how do i do that in swiftUI? right now it looks like this
struct ContentView: View {
var body: some View {
VStack {
HStack {
VStack(alignment: .leading, spacing: 130) {
Text("Title")
.font(.headline)
.foregroundColor(.primary)
Text("text")
.font(.subheadline)
.foregroundColor(.secondary)
Text("padding")
}
.padding(.vertical)
Spacer()
Image("rightTag")
.resizable(capInsets: .init(top: 0, leading: 0, bottom: 0, trailing: 0), resizingMode: .stretch)
.aspectRatio(contentMode: .fit)
.frame(maxWidth: 20)
}
.frame(maxWidth: screen.width - 60)
.padding(.leading)
.background(.white)
.cornerRadius(20)
}
}
}
how can i stretch its height to fit this outer frame? ragular resizable and stuff can't get it done.
any helped would be wonderful! Thanks!
sry i didn't make myself clear earllier.
Here is possible approach. However as I see now you'd rather need to stretch not the entire original image, but only middle of it, so in real project it would be needed to make your image tri-part and apply below stretching approach only to middle (square) part.
Approach uses asynchronous state update, so works in Live Preview / Simulator / RealDevice. (Tested with Xcode 11.2 / iOS 13.2)
struct ContentView: View {
#State private var textHeigh: CGFloat = .zero
var body: some View {
VStack {
HStack(alignment: .top) {
VStack(alignment: .leading, spacing: 130) {
Text("Title")
.font(.headline)
.foregroundColor(.primary)
Text("text")
.font(.subheadline)
.foregroundColor(.secondary)
Text("padding")
}
.padding(.vertical)
.alignmentGuide(.top, computeValue: { d in
DispatchQueue.main.async {
self.textHeigh = d.height // !! detectable height of left side text
}
return d[.top]
})
Spacer()
Image("rightTag")
.resizable()
.frame(maxWidth: 20, maxHeight: max(60, textHeigh)) // 60 just for default
}
.frame(maxWidth: screen.width - 60)
.padding(.leading)
.background(Color.white)
}
}
}
Added on the 24th of July:
This line of code fixes the space in the detail view. However... in the list view the title has become a lot smaller too.
.navigationBarTitle(Text("Egg management"), displayMode: .inline)
Added on the 23th of July:
Thanks to the tips I made a lot of progress. Especially the tip to add borders does wonders. You see exactly what happens!
However, there seems to be a difference between the Xcode Preview canvas, the simulator and the physical device. Is this a bug because -after all- it is still beta? Or is there anything I can do?
As you can see in the images... only in the Xcode Preview canvas the view connects to the top of the screen.
I believe it has something to do with the tabbar. Since when I look at the Xcode Preview canvas with the tabbar... that space above is also there. Any idea how to get rid of that?
Original postings:
This is my code for a detailed list view:
import SwiftUI
struct ContentDetail : View {
#State var photo = true
var text = "Een kip ..."
var imageList = "Dag-3"
var day = "3.circle"
var date = "9 augustus 2019"
var imageDetail = "Day-3"
var weight = "35.48"
var body: some View {
VStack (alignment: .center, spacing: 10) {
Text(date)
.font(.title)
.fontWeight(.medium)
ZStack (alignment: .topLeading){
Image(photo ? imageDetail : imageList)
.resizable()
.aspectRatio(contentMode: .fit)
.background(Color.black)
.padding(.trailing, 0)
.tapAction {
self.photo.toggle() }
HStack {
Image(systemName: day)
.resizable()
.padding(.leading, 10)
.padding(.top, 10)
.frame(width: 40, height: 32)
.foregroundColor(.white)
Spacer()
Image(systemName: photo ? "photo" : "pencil.circle")
.resizable()
.padding(.trailing, 10)
.padding(.top, 10)
.frame(width: 32, height: 32)
.foregroundColor(.white)
}
}
Text(text)
.lineLimit(6)
.frame(minWidth: 0, maxWidth: .infinity, alignment: .leading)
.padding(.leading, 6)
} .padding(20)
}
}
#if DEBUG
struct ContentDetail_Previews : PreviewProvider {
static var previews: some View {
ContentDetail()
}
}
#endif
Also included is the preview canvas. What I don't get is how I can make sure the text and photo are aligned to the top (instead of the middle). I tried with Spacers, padding etc.
I must be overseeing something small I guess... but. Can somebody point me in the right direction? Thanks.
Added:
After both answers I added a Spacer() after the last text. In Xcode in the preview canvas everything looks okay now. But on my connected iPhone 7 Plus there are some problems: the view is not aligned to the top, and the image is cropped (icon on the right is gone; white banding to the right).
Adding a Spacer() after the last text shifts everything to the top. Tested on iPhone Xr simulator (not preview).
...
Text(text)
.lineLimit(6)
.frame(minWidth: 0, maxWidth: .infinity, alignment: .leading)
.padding(.leading, 6)
Spacer()
}
To remove the space at the top:
VStack {
...
}
.padding(20)
.navigationBarTitle("TITLE", displayMode: .inline)
Think in terms of what a Spacer() does. It "moves" the views as far apart as it can - at least, without a specific space.
So you have this:
VStack {
Text
ZStack {
Image
HStack {
Image
Spacer()
Image
}
}
Text
}
All told, going from inner to outer, you have a horizontal stack of two images placed as far apart (the spacer is between them) inside of a "Z axis" stack that places an image on top of them, inside of a vertical stack that has some text above it.
So if you want to move everything in that vertical stack to the top, you simply need to add one last spacer:
VStack {
Text
ZStack {
Image
HStack {
Image
Spacer()
Image
}
}
Text
Spacer() // <-- ADD THIS
}
Last note: Don't be afraid to adding additional "stacks" to your view. In terms of memory footprint, it's really just a single view with no performance hit.
EDIT: I took your original view and changed everything to placeholders...
var body: some View {
VStack (alignment: .center, spacing: 10) {
Text("Text #1")
.font(.title)
.fontWeight(.medium)
ZStack (alignment: .topLeading) {
Text( "Image #1")
HStack {
Text("Image #2")
Spacer()
Text("Image #3")
}
}
Text("Text #2")
.lineLimit(6)
.frame(minWidth: 0, maxWidth: .infinity, alignment: .leading)
.padding(.leading, 6)
} .padding(20)
}
As expected, everything is vertically centered. Adding a Spacer() below "Text #2" throws everything to the top. A couple of thoughts:
Starting there, and add in your Image views one by one. Add in the modifiers like that also.
I don't have the specific images you are rendering, so maybe put a noticeable background color on various things (orange is my personal favorite) and see if the top Image is actually on top but the image makes it appear as though it isn't. A border would work pretty well too.