Amaya, miembro de este gran staff, nos hizo el favor de redactar esta sección ya que conoce perfectamente dicho tema.
Solución:
Un ZStack ayudará a resolver esto al permitirnos superponer vistas sin que una afecte el diseño de la otra.
Para el texto:
.frame(minWidth: 0, maxWidth: .infinity)
para expandir el texto horizontalmente al tamaño de su padre
.frame(minHeight: 0, maxHeight: .infinity)
es útil en otras situaciones
En cuanto a la imagen:
.aspectRatio(contentMode: .fill)
para hacer que la imagen mantenga su relación de aspecto en lugar de aplastarse al tamaño de su marco.
.layoutPriority(-1)
para des-priorizar el diseño de la imagen para evitar que expanda su padre (el ZStack
dentro de ForEach
en nuestro caso).
El valor de layoutPriority
solo debe ser menor que las vistas principales, que se establecerán en 0 de forma predeterminada. Tenemos que hacer esto porque SwiftUI colocará a un niño antes que a su padre, y el padre tiene que lidiar con el tamaño del niño a menos que prioricemos manualmente de manera diferente.
El .clipped()
El modificador usa el marco delimitador para enmascarar la vista, por lo que deberá configurarlo para recortar cualquier imagen que no tenga una relación de aspecto de 1: 1.
var body: some View
HStack
ForEach(0..<3, id: .self) index in
ZStack
Image(systemName: "doc.plaintext")
.resizable()
.aspectRatio(contentMode: .fill)
.layoutPriority(-1)
VStack
Spacer()
Text("yes")
.frame(minWidth: 0, maxWidth: .infinity)
.background(Color.white)
.clipped()
.aspectRatio(1, contentMode: .fit)
.border(Color.red)
Editar: Si bien los lectores de geometría son súper útiles, creo que deberían evitarse siempre que sea posible. Es más limpio dejar que SwiftUI haga el trabajo. Esta es mi solución inicial con un Geometry Reader
eso funciona igual de bien.
HStack
ForEach(0..<3, id: .self) index in
ZStack
GeometryReader proxy in
Image(systemName: "pencil")
.resizable()
.scaledToFill()
.frame(width: proxy.size.width)
VStack
Spacer()
Text("yes")
.frame(width: proxy.size.width)
.background(Color.white)
.clipped()
.aspectRatio(1, contentMode: .fit)
.border(Color.red)
Me funciona, pero no sé por qué es necesario cornerRadius ...
import SwiftUI
struct ClippedImage: View
let imageName: String
let width: CGFloat
let height: CGFloat
init(_ imageName: String, width: CGFloat, height: CGFloat)
self.imageName = imageName
self.width = width
self.height = height
var body: some View
ZStack
Image(imageName)
.resizable()
.aspectRatio(contentMode: .fill)
.frame(width: width, height: height)
.cornerRadius(0) // Necessary for working
.frame(width: width, height: height)
struct ClippedImage_Previews: PreviewProvider
static var previews: some View
ClippedImage("dishLarge1", width: 100, height: 100)
Recuerda que puedes dar visibilidad a este artículo si te valió la pena.