Recursos
Primero hay que agregar los recursos en el catálogo de recursos (i.e. "Asset Catalog") dentro de un "Image Set" con las imágenes 1x, 2x y 3x; para luego referenciarlo por nombre desde el código.
Un "Image Set" puede tener las imágenes, no solo para cualquier dispositivo (i.e. "Universal"), sino que también puede definir imágenes para un dispositivo específico (e.g. "iPhone"), en la sección "Devices" del inspector de atributos. Asímismo, se puede discriminar las imágenes por apariencia del dispositivo (clara y obscura).
La plantilla de aplicación multiplataforma incluye un catálogo de recursos llamado "Preview Assets" donde se puede agregar algunas imágenes al proyecto disponibles solo en tiempo de desarrollo, pero que no son incluidas en el binario final de la aplicación.
Cuando se agrega una imagen al catálogo de recursos, Xcode crea una estructura ImageResource para representarlo, y esta estructura se asigna a una propiedad estática que puede ser referenciada para cargar la imagen. El nombre de la propiedad es definido por el nombre del "Image Set", pero en minúsculas.
Componente Image
El componente para mostrar una imagen se llama Image. Estos son algunos de los constructores:
-
init(_:): Crea una imagen con unImageResource, que es una estructura que representa una imagen del catálogo de recursos. -
init(_:bundle:): Crea una imagen con unStringque representa el nombre de la imagen dentro del catálogo de recursos y elBundleque lo contiene. -
init(systemName:variableValue:): Crea unImagecon un SF symbol. El argumentovariableValuees un valor entre0.0y1.0que personaliza la apariencia del símbolo. Si el símbolo no aceptavariableValue, este valor no tiene efecto. -
init(uiImage:): Crea unImagea partir de unUIImage.
struct ContentView: View {
var body: some View {
VStack {
Image(ImageResource(name: "Myimage", bundle: Bundle.main))
.resizable()
.scaledToFit()
Image(.myimage)
.resizable()
.scaledToFit()
Image("Myimage")
.resizable()
.scaledToFit()
Image(systemName: "timelapse", variableValue: 0.5)
}
}
}
Ajustar el tamaño de una imagen
Por defecto, un Image es del tamaño de su contenido. Por esta razón, si la imagen es más grande que la ventana, la vista se extenderá más allá de los límites de la pantalla.
ALERTA: La imagen es independiente de la vista contenedora Image. Si se cambia el tamaño de la vista con el modificador frame(width:height:alignment:), la imagen va a permanecer con el tamaño original. Para que la imagen se ajuste al contenedor, se debe usar alguno de los siguientes modificadores:
-
clipped(antialiased:): Corta la imagen dentro del recuadro. Esto reduce el tamaño de la imagen visible, pero esta todavía está presente con su tamaño original, independiente del tamaño del contenedor. -
resizable(capInsets:resizingMode:): Cambia el tamaño de la imagen para que se ajuste al recuadro.capInsetsindica qué parte de la imagen no debería ser ajustada yresizingModeespecifica cómo es que la imagen va a ajustarse al recuadro (sea estirándosestretcho copiándosetile). -
aspectRatio(_:contentMode:): Cambia la relación de aspecto de la imagen. -
scaledToFit(): Escala la imagen para rellenar el contenedor conservando la relación de aspecto. -
scaledToFill(): Escala la imagen para rellenar el contenedor ignorando la relación de aspecto original.
clipped() corta la imagen dentro del recuadro, sin alterar el tamaño de la misma.
struct ContentView: View {
var body: some View {
VStack {
Image(.myimage)
.frame(width: 100, height: 100)
.clipped()
}
}
}
resizable() crea una vista estirando la imagen, estropeando la relación de aspecto de la imagen. No tiene sentido aplicar .clipped() después de resizable().
struct ContentView: View {
var body: some View {
VStack {
Image(.myimage)
.resizable()
.frame(width: 100, height: 100)
}
}
}
Para conservar la relación de aspecto al hacer .resizable(), hay que usar aspectRatio(_:contentMode:):). Si se usa contentMode = .fit se consigue el mismo resultado que con .scaleToFit(). Si se usa contentMode = .fill se consigue el mismo resultado que con .scaleToFill(). En ambos casos, la relación de aspecto se preserva.
struct ContentView: View {
var body: some View {
VStack {
Image(.myimage)
.resizable()
.aspectRatio(contentMode: .fit)
// .scaleToFit()
.frame(width: 100, height: 100)
}
}
}
struct ContentView: View {
var body: some View {
VStack {
Image(.myimage)
.resizable()
.aspectRatio(contentMode: .fill)
// .scaleToFill()
.frame(width: 100, height: 100)
}
}
}
Al usar (contentMode: .fill) es posible que la imagen exceda el área limitada por el recuadro. Para que esto no ocurra, se usa el modificador clipped(antialiased:) visto antes.
struct ContentView: View {
var body: some View {
VStack {
Image(.myimage)
.resizable()
.aspectRatio(contentMode: .fill)
.frame(width: 100, height: 100)
.clipped()
}
}
}
Aplicar otros modificadores a la imagen
Todos los modificadores de View pueden ser aplicados también a Image. Por ejemplo:
-
shadow(color:radius:x:y:)agrega una sombra a la vista. -
padding(_:_:)agrega un relleno a ciertos bordes de la vista. -
blur(radius:opaque:): Agrega un efecto de difuminado.radiusespecifica qué tan difuso será el efecto yopaqueindica si el efecto será opaco o transparente. -
scaleEffect(_:anchor:): Escala el contenido de la vista de forma horizontal y vertical aplicando una matriz de transformación de escala.
struct ContentView: View {
var body: some View {
VStack {
Image(.myimage)
.resizable()
.aspectRatio(contentMode: .fill)
.frame(width: 300, height: 400)
.clipped()
.shadow(radius: 50, x:10, y: 10)
.padding(20)
.scaleEffect(CGSize(width: 0.7, height: 0.5))
.blur(radius: 5, opaque: false)
}
}
}
Adaptando el tamaño de la imagen al tamaño de la fuente
Se puede ajustar el tamaño de la imagen con base en la fuente dinámica seleccionada por el usuario, a través del "property wrapper" ScaledMetric.
Este "property wrapper" define un número que escala automáticamente con base en el "Dynamic Type" seleccionado por el usuario. En la forma de uso más simple, simplemente hay que crear una propiedad numérica anotada con @ScaledMetric y el "property wrapper" hará lo suyo.
struct ContentView: View {
@ScaledMetric var imageSize = 100.0
var body: some View {
Image(systemName: "cloud.sun.bolt.fill")
.resizable()
.frame(width: imageSize, height: imageSize)
}
}
Si es necesario escalar con respecto a un tipo de estilo específico, se puede usar el parámetro relativeTo.
@ScaledMetric(relativeTo: .largeTitle) var imageSize = 100.0







Top comments (0)