Reputation: 1273
I'm attempting to make a widget extension with two text labels and an image. The two labels need to be in the top left and the image in the bottom right. I've been unable to get this working correctly.
Is there a proper way of doing this without having to use a Spacer() or an overlay image which isn't what I need. Very new to SwiftUI. Any help or pointers would be greatly appreciated.
VStack (alignment: .leading){
Text("Title")
.font(.headline)
.fontWeight(.regular)
.lineLimit(1)
Text("subtitle")
.font(.title3)
.fontWeight(.bold)
.lineLimit(1)
.allowsTightening(true)
HStack {
Spacer(minLength: 15)
Image("fish")
.resizable()
.frame(width: 120, height: 80)
}
}
.padding(.top)
.padding(.leading)
Upvotes: 1
Views: 1733
Reputation: 1273
I think I've managed to get this working, well as close as I could get it. Seems to be a bit better than before. Mildly satisfied but working now.
ZStack {
VStack (alignment: .leading){
Text("Title")
.font(.body)
.fontWeight(.bold)
.lineLimit(1)
.allowsTightening(true)
Text("subtitle")
.font(.title)
.fontWeight(.regular)
HStack(alignment: .bottom){
Spacer()
Image("fish")
.resizable()
.frame(width: 120, height: 80)
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .bottomTrailing)
.offset(x: 5, y: -10)
// padding for images with frame bigger than actual image
}
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity, alignment: .leading)
}
.padding(12)
}
.background(Color(UIColor.secondarySystemBackground))
Upvotes: 0
Reputation: 5135
There are a bunch of ways to build a layout like that. What you have is almost working, you just need a Spacer
between the text and image to shove the image down:
VStack (alignment: .leading) {
Text("Title")
.font(.headline)
.fontWeight(.regular)
.lineLimit(1)
Text("subtitle")
.font(.title3)
.fontWeight(.bold)
.lineLimit(1)
.allowsTightening(true)
Spacer(minLength: 0) // <-- add spacer here
HStack {
Spacer(minLength: 15)
Image("fish")
.resizable()
.frame(width: 120, height: 80)
}
}
.padding(.top)
.padding(.leading)
The only other change I would suggest is avoiding the hard-coded image size, since widgets are different sizes on different phones. You could have the image expand to fit the available width while preserving your image’s 3:2 aspect ratio like this:
VStack(alignment: .leading) {
Text("Title")
.font(.headline)
.fontWeight(.regular)
Text("subtitle")
.font(.title3)
.fontWeight(.bold)
.allowsTightening(true)
Spacer(minLength: 0)
Image("fish")
.resizable()
.aspectRatio(3/2, contentMode: .fit)
}
.lineLimit(1)
.padding(.leading)
.padding(.top)
Or if you want the fixed-size image and would prefer to have the text overlap it on smaller screens, you could use a ZStack
like this:
ZStack(alignment: .bottomTrailing) {
Image("fish")
.resizable()
.frame(width: 120, height: 80)
VStack (alignment: .leading) {
Text("Title")
.font(.headline)
.fontWeight(.regular)
Text("subtitle")
.font(.title3)
.fontWeight(.bold)
.allowsTightening(true)
}
.lineLimit(1)
.padding()
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading)
}
As I said, there are a bunch of ways to solve this!
Upvotes: 1