I want to have a view that shows two elements created with a customShape (it is basically the same Shape as RoundedRectangle(cornerRadius:25.0) but combined with a normal rectangle to make 2 corners sharped). The problem is that when I try to combine these two views (miking it a Capsule() I am not able to modify its proportion. I’d like the image to occupy only the 25% of the pill and the text the 75% lasting. But I am not able to accomplish this. This is a photo of what i have :
I tried using GeometryReader but I don’t know if it is a good solution or if I don’t know how to use it but I get this:
The code of the main view is:
struct CardHomeContent: View {
var body: some View {
ZStack {
RoundedRectangle(cornerRadius: /*@START_MENU_TOKEN@*/25.0/*@END_MENU_TOKEN@*/)
HStack(spacing:0) { //Contenido
ImageContent(image:"Croissant")
TextCardContent()
}
}
.clipShape(RoundedRectangle(cornerRadius: 25))
.padding(.horizontal)
}
}
ImageView is:
struct ImageContent: View {
let image : String
var body: some View {
ZStack {
Image(image)
.resizable()
.scaledToFill()
}
}
}
And the TextView:
struct TextCardContent: View {
let uiFont: UIFont = .systemFont(ofSize: 13)
let description = "Unos croissants que harán chuparte los dedos llenos de mantequilla"
var justifiedTest: String {
description.justified(font: uiFont, maxWidth: 165)
}
var body: some View {
ZStack {
RoundedRectangleCustomShapeRight().foregroundStyle(Color.white)
HStack {
VStack {
Text("Croissants tradicionales").bold().lineLimit(2).minimumScaleFactor(0.4)
Text(description).font(.footnote).foregroundStyle(Color.gray).lineLimit(3).minimumScaleFactor(0.5)
.multilineTextAlignment(.leading)
}
.padding(.all)
Text(">")
.padding(.trailing)
}
}
}
}
So I would appreciate if someone could come up with any idea.
2
Answers
From my perspective, the simplest way to accomplish this is to wrap CardHomeContent into a
GeometryReader
, and then calculate the width of each card view part. i.e, ImageContent has 0.25 and TextCardContent will take 0.75, of the total width.You also can remove ZStack in
ImageContent
, since it was an Image only and its parent is a ZStack already. However, ImageContent need to change toscaledToFit
or you can keepscaledToFill
withclipped()
, to avoid overwhelming.If you are fixing the height and the width of the card views then there is an easy solution: you just need to wrap the shape with a
GeometryReader
, as explained in another answer.However, if you want the cards to adopt a natural height, it’s a bit more tricky. Here are two techniques:
1. Use a hidden footprint with an overlay
GeometryReader
, which measures the size of the footprint.By default,
CardHomeContent
will grab as much width as possible, because the footprint usesmaxWidth: .infinity
. The width can be constrained by applying aframe
toCardHomeContent
:2. Use a custom layout
Another way to solve the problem is using a custom
Layout
. In the following example implementation, the layout is only expecting to have two subviews and the height of the overall card is determined by the second of the subviews: