Skip to content

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:

  1. Use Liquid Glass nativo no iOS 26+
  2. Forneça um fallback consistente para iOS 18-25
  3. 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:

swift
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

swift
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+)

swift
self.glassEffect(interactive ? .regular.interactive() : .regular, in: shape)
    .clipShape(shape)

No iOS 26+, usamos o modificador nativo com:

  • Variante .regular para 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)

swift
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

swift
Button("Adicionar Item") {
    // ação
}
.padding()
.glassedEffect(in: Capsule())

Botão de Ação Flutuante Interativo

swift
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

swift
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

swift
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:

swift
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.

Referências