¿Qué hace Sistema de Diseño Liquid Glass (iOS 26)?
Patrones para implementar el Liquid Glass de Apple: un material dinámico que desenfoca el contenido detrás, refleja el color y la luz del contenido circundante, y reacciona a interacciones táctiles y de puntero. Cubre integración con SwiftUI, UIKit y WidgetKit.
Cuándo activarlo
- Al construir o actualizar apps para iOS 26+ con el nuevo lenguaje de diseño
- Al implementar botones, tarjetas, barras de herramientas o contenedores de estilo vidrio
- Al crear transiciones morphing entre elementos de vidrio
- Al aplicar efectos Liquid Glass a widgets
- Al migrar efectos de material/desenfoque existentes a la nueva API Liquid Glass
Patrón Principal — SwiftUI
Efecto básico de vidrio
La forma más sencilla de añadir Liquid Glass a cualquier vista:
Text("¡Hola, Mundo!")
.font(.title)
.padding()
.glassEffect() // Por defecto: variante regular, forma de cápsula
Personalizando forma y tinte
Text("¡Hola, Mundo!")
.font(.title)
.padding()
.glassEffect(.regular.tint(.orange).interactive(), in: .rect(cornerRadius: 16.0))
Opciones clave de personalización:
.regular— efecto de vidrio estándar.tint(Color)— añade un tinte de color para dar énfasis.interactive()— reacciona a interacciones táctiles y de puntero- Forma:
.capsule(por defecto),.rect(cornerRadius:),.circle
Estilos de botón de vidrio
Button("Haz clic") { /* acción */ }
.buttonStyle(.glass)
Button("Importante") { /* acción */ }
.buttonStyle(.glassProminent)
GlassEffectContainer para múltiples elementos
Envuelve siempre varias vistas de vidrio en un contenedor para mejorar el rendimiento y el morphing:
GlassEffectContainer(spacing: 40.0) {
HStack(spacing: 40.0) {
Image(systemName: "scribble.variable")
.frame(width: 80.0, height: 80.0)
.font(.system(size: 36))
.glassEffect()
Image(systemName: "eraser.fill")
.frame(width: 80.0, height: 80.0)
.font(.system(size: 36))
.glassEffect()
}
}
El parámetro spacing controla la distancia de fusión: los elementos más cercanos combinan sus formas de vidrio.
Uniendo efectos de vidrio
Combina múltiples vistas en una sola forma de vidrio con glassEffectUnion:
@Namespace private var namespace
GlassEffectContainer(spacing: 20.0) {
HStack(spacing: 20.0) {
ForEach(symbolSet.indices, id: \.self) { item in
Image(systemName: symbolSet[item])
.frame(width: 80.0, height: 80.0)
.glassEffect()
.glassEffectUnion(id: item < 2 ? "group1" : "group2", namespace: namespace)
}
}
}
Transiciones morphing
Crea morphing suave cuando los elementos de vidrio aparecen/desaparecen:
@State private var isExpanded = false
@Namespace private var namespace
GlassEffectContainer(spacing: 40.0) {
HStack(spacing: 40.0) {
Image(systemName: "scribble.variable")
.frame(width: 80.0, height: 80.0)
.glassEffect()
.glassEffectID("pencil", in: namespace)
if isExpanded {
Image(systemName: "eraser.fill")
.frame(width: 80.0, height: 80.0)
.glassEffect()
.glassEffectID("eraser", in: namespace)
}
}
}
Button("Alternar") {
withAnimation { isExpanded.toggle() }
}
.buttonStyle(.glass)
Extender el desplazamiento horizontal debajo de la barra lateral
Para permitir que el contenido de desplazamiento horizontal se extienda debajo de una barra lateral o inspector, asegúrate de que el contenido del ScrollView llegue a los bordes inicial/final del contenedor. El sistema maneja automáticamente el comportamiento de desplazamiento debajo de la barra lateral cuando el diseño se extiende hasta los bordes; no se necesita ningún modificador adicional.
Patrón Principal — UIKit
UIGlassEffect básico
let glassEffect = UIGlassEffect()
glassEffect.tintColor = UIColor.systemBlue.withAlphaComponent(0.3)
glassEffect.isInteractive = true
let visualEffectView = UIVisualEffectView(effect: glassEffect)
visualEffectView.translatesAutoresizingMaskIntoConstraints = false
visualEffectView.layer.cornerRadius = 20
visualEffectView.clipsToBounds = true
view.addSubview(visualEffectView)
NSLayoutConstraint.activate([
visualEffectView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
visualEffectView.centerYAnchor.constraint(equalTo: view.centerYAnchor),
visualEffectView.widthAnchor.constraint(equalToConstant: 200),
visualEffectView.heightAnchor.constraint(equalToConstant: 120)
])
// Añadir contenido al contentView
let label = UILabel()
label.text = "Vidrio Líquido"
label.translatesAutoresizingMaskIntoConstraints = false
visualEffectView.contentView.addSubview(label)
NSLayoutConstraint.activate([
label.centerXAnchor.constraint(equalTo: visualEffectView.contentView.centerXAnchor),
label.centerYAnchor.constraint(equalTo: visualEffectView.contentView.centerYAnchor)
])
UIGlassContainerEffect para múltiples elementos
let containerEffect = UIGlassContainerEffect()
containerEffect.spacing = 40.0
let containerView = UIVisualEffectView(effect: containerEffect)
let firstGlass = UIVisualEffectView(effect: UIGlassEffect())
let secondGlass = UIVisualEffectView(effect: UIGlassEffect())
containerView.contentView.addSubview(firstGlass)
containerView.contentView.addSubview(secondGlass)
Efectos de borde de desplazamiento
scrollView.topEdgeEffect.style = .automatic
scrollView.bottomEdgeEffect.style = .hard
scrollView.leftEdgeEffect.isHidden = true
Integración de vidrio en barras de herramientas
let favoriteButton = UIBarButtonItem(image: UIImage(systemName: "heart"), style: .plain, target: self, action: #selector(favoriteAction))
favoriteButton.hidesSharedBackground = true // Optar por no usar el fondo de vidrio compartido
Patrón Principal — WidgetKit
Detección del modo de renderizado
struct MyWidgetView: View {
@Environment(\.widgetRenderingMode) var renderingMode
var body: some View {
if renderingMode == .accented {
// Modo teñido: fondo de vidrio con tinte blanco y temático
} else {
// Modo color completo: apariencia estándar
}
}
}
Grupos de acento para jerarquía visual
HStack {
VStack(alignment: .leading) {
Text("Título")
.widgetAccentable() // Grupo de acento
Text("Subtítulo")
// Grupo primario (por defecto)
}
Image(systemName: "star.fill")
.widgetAccentable() // Grupo de acento
}
Renderizado de imágenes en modo acentuado
Image("myImage")
.widgetAccentedRenderingMode(.monochrome)
Fondo del contenedor
VStack { /* contenido */ }
.containerBackground(for: .widget) {
Color.blue.opacity(0.2)
}
Decisiones de diseño clave
| Decisión | Justificación |
|---|---|
Envolver con GlassEffectContainer | Optimización del rendimiento, permite morphing entre elementos de vidrio |
Parámetro spacing | Controla la distancia de fusión: ajusta qué tan cerca deben estar los elementos para combinarse |
@Namespace + glassEffectID | Permite transiciones morphing suaves al cambiar la jerarquía de vistas |
Modificador interactive() | Adhesión explícita para reacciones táctiles/de puntero; no todo el vidrio debe responder |
UIGlassContainerEffect en UIKit | Mismo patrón de contenedor que en SwiftUI para consistencia |
| Modo de renderizado acentuado en widgets | El sistema aplica vidrio teñido cuando el usuario selecciona la pantalla de inicio teñida |
Mejores prácticas
- Usa siempre
GlassEffectContaineral aplicar vidrio a múltiples vistas hermanas; permite morphing y mejora el rendimiento de renderizado - Aplica
.glassEffect()después de otros modificadores de apariencia (frame, font, padding) - Usa
.interactive()solo en elementos que respondan a la interacción del usuario (botones, elementos alternables) - Elige el espaciado con cuidado en los contenedores para controlar cuándo se fusionan los efectos de vidrio
- Usa
withAnimational cambiar jerarquías de vistas para habilitar transiciones morphing suaves - Prueba en todas las apariencias — modo claro, modo oscuro y modos acentuado/teñido
- Asegura el contraste de accesibilidad — el texto sobre vidrio debe seguir siendo legible
Antipatrones a evitar
- Usar múltiples vistas
.glassEffect()independientes sin unGlassEffectContainer - Anidar demasiados efectos de vidrio — degrada el rendimiento y la claridad visual
- Aplicar vidrio a cada vista — resérvalo para elementos interactivos, barras de herramientas y tarjetas
- Olvidar
clipsToBounds = trueen UIKit al usar esquinas redondeadas - Ignorar el modo de renderizado acentuado en widgets — rompe la apariencia de la pantalla de inicio teñida
- Usar fondos opacos detrás del vidrio — anula el efecto de translucidez
Cuándo usarlo
- Barras de navegación, barras de herramientas y barras de pestañas con el nuevo diseño de iOS 26
- Botones de acción flotantes y contenedores tipo tarjeta
- Controles interactivos que necesitan profundidad visual y retroalimentación táctil
- Widgets que deben integrarse con la apariencia Liquid Glass del sistema
- Transiciones morphing entre estados de interfaz relacionados