Efeito Glass do iOS 26 com Compatibilidade Retroativa no SwiftUI
Introdução
O iOS 26 introduziu o Liquid Glass, a evolução de design mais significativa da Apple desde o iOS 7. Este material translúcido e dinâmico reflete e refrata o conteúdo ao redor, criando um efeito visual sofisticado para elementos de navegação e controles.
Embora o novo modificador .glassEffect() torne a implementação desse design simples, a maioria dos apps ainda precisa suportar versões anteriores do iOS. Este artigo mostra como criar uma extensão de View reutilizável que usa Liquid Glass nativo no iOS 26+ e faz fallback para .thinMaterial em versões anteriores.
O Desafio
Quando você tenta usar .glassEffect() em versões do iOS anteriores à 26, seu app não compila. Você precisa de uma solução que:
- Use Liquid Glass nativo no iOS 26+
- Forneça um fallback consistente para iOS 18-25
- Mantenha seu código de view limpo e simples
A Solução
Aqui está uma extensão de View que lida com ambos os casos de forma elegante:
import SwiftUI
extension View {
/// Aplica um efeito glass com compatibilidade futura.
/// - No iOS 26+: Usa `.glassEffect()` nativo para aparência liquid glass
/// - No iOS 18-25: Faz fallback para `.thinMaterial` para consistência
@ViewBuilder
func glassedEffect(in shape: some Shape, interactive: Bool = false) -> some View {
if #available(iOS 26.0, *) {
self.glassEffect(interactive ? .regular.interactive() : .regular, in: shape)
.clipShape(shape)
} else {
background {
shape.fill(.thinMaterial)
}
.clipShape(shape)
}
}
}Como Funciona
Vamos analisar os componentes principais:
1. O Atributo @ViewBuilder
O atributo @ViewBuilder permite que a função retorne diferentes tipos de view dependendo da versão do iOS. Sem ele, o Swift exigiria que ambos os branches retornassem o mesmo tipo.
2. Verificação de Disponibilidade
if #available(iOS 26.0, *) {Esta verificação em tempo de compilação garante que o código do Liquid Glass só execute no iOS 26+. O compilador sabe que isso é seguro e permite o modificador .glassEffect() nesse branch.
3. Liquid Glass Nativo (iOS 26+)
self.glassEffect(interactive ? .regular.interactive() : .regular, in: shape)
.clipShape(shape)No iOS 26+, usamos o modificador nativo com:
- Variante
.regularpara aparência glass padrão .interactive()para controles que devem responder ao toque com efeitos de escala e brilho- O parâmetro shape controla o limite do glass
4. Fallback Material (iOS 18-25)
background {
shape.fill(.thinMaterial)
}
.clipShape(shape)Para versões anteriores, .thinMaterial fornece um efeito translúcido similar que combina bem com o design do sistema.
Exemplos de Uso
Botão Básico com Efeito Glass
Button("Adicionar Item") {
// ação
}
.padding()
.glassedEffect(in: Capsule())Botão de Ação Flutuante Interativo
Button(action: adicionarItem) {
HStack(spacing: 8) {
Image(systemName: "plus")
.font(.system(size: 20, weight: .semibold))
Text("Adicionar Nível")
}
.foregroundStyle(Color.primary)
.padding(.horizontal, 20)
.frame(height: 58)
.glassedEffect(in: Capsule(), interactive: true)
.shadow(color: Color.black.opacity(0.12), radius: 12, y: 8)
}Card com Cantos Arredondados
VStack(alignment: .leading) {
Text("Estatísticas")
.font(.headline)
Text("Seu resumo semanal")
.font(.subheadline)
.foregroundStyle(.secondary)
}
.padding()
.glassedEffect(in: RoundedRectangle(cornerRadius: 16))Botão de Ícone Circular
Button(action: mostrarConfiguracoes) {
Image(systemName: "gear")
.font(.title2)
.frame(width: 44, height: 44)
.glassedEffect(in: Circle(), interactive: true)
}Considerações de Design
Quando Usar Efeitos Glass
De acordo com as diretrizes de design da Apple, o Liquid Glass deve ser reservado para a camada de navegação, não para o conteúdo principal. Pense em toolbars, botões de ação flutuantes e overlays de controle.
Evite Aninhar Glass
Glass não pode amostrar outros elementos glass. Se você tiver múltiplos elementos glass próximos uns dos outros, envolva-os em um GlassEffectContainer no iOS 26+ para garantir comportamento visual consistente.
Expandindo para Mais Opções
Você pode expandir a extensão para suportar mais variantes de glass:
extension View {
@ViewBuilder
func glassedEffect(
in shape: some Shape,
variant: GlassVariant = .regular,
interactive: Bool = false
) -> some View {
if #available(iOS 26.0, *) {
let glass: Glass = switch variant {
case .regular: .regular
case .clear: .clear
}
self.glassEffect(interactive ? glass.interactive() : glass, in: shape)
.clipShape(shape)
} else {
background {
shape.fill(.thinMaterial)
}
.clipShape(shape)
}
}
}
enum GlassVariant {
case regular
case clear
}Conclusão
Suportar o Liquid Glass do iOS 26 mantendo compatibilidade retroativa não requer abstrações complexas. Uma simples extensão de View com @ViewBuilder e verificações #available oferece o melhor dos dois mundos: Liquid Glass nativo em dispositivos mais novos e um fallback elegante de material em dispositivos mais antigos.
Este padrão mantém seu código de view limpo—basta chamar .glassedEffect(in: Capsule()) e deixar a extensão cuidar do resto.

