Shadow: essência, criação de sombras em aplicações móveis

Autor: IT Sectr Publicado: 2026-02-28 Tempo de leitura: 9 min

Shadow (sombra) — um efeito visual em interfaces móveis que cria a ilusão de profundidade e hierarquia entre elementos. As sombras mostram qual elemento está mais acima no plano z e, portanto, é mais importante ou interativo. De acordo com as Material Design Guidelines (Google, 2026), as sombras do sistema usam cinco níveis-chave de elevation: 0 dp (plano), 1–4 dp (botões), 6–12 dp (cartões), 16–24 dp (diálogos), 24+ dp (janelas modais). Saiba mais sobre a altura dos elementos no artigo sobre Elevation.

Principais pontos

  • Sombra (shadow) — efeito visual que cria profundidade escurecendo a área sob um elemento com desfoque nas bordas.
  • No iOS, as sombras são definidas através das propriedades de CALayer: shadowColor, shadowOffset, shadowRadius, shadowOpacity.
  • No Android, as sombras são gerenciadas através de elevation (Material Design) ou renderização personalizada via OutlineProvider.
  • Jetpack Compose suporta sombras através de Modifier.shadow() e elevation em Card/Surface.
  • No Flutter, as sombras são implementadas através de BoxShadow em BoxDecoration ou via PhysicalModel.

O que é sombra na IU?

Sombra (shadow) em interfaces de utilizador é um efeito visual que simula iluminação e profundidade. A sombra é criada desenhando uma cópia escura e desfocada de um elemento, deslocada em relação ao original. No design móvel, as sombras têm três funções: mostram hierarquia (quanto mais alto o elemento, mais longa a sombra), sinalizam interatividade (botões com sombra parecem pressionáveis), separam o conteúdo do fundo (cartões com sombra leem-se como blocos separados).

No Material Design da Google, as sombras estão inextricavelmente ligadas ao conceito de elevation. Cada elemento ocupa uma certa altura na coordenada z, e a sombra é uma projeção da iluminação superior. As Human Interface Guidelines da Apple não prescrevem um sistema rigoroso de alturas, mas recomendam usar sombras para criar hierarquia visual e profundidade nas interfaces.

De acordo com um estudo do Nielsen Norman Group (2024), sombras colocadas corretamente reduzem o tempo para encontrar um elemento interativo em 24%. As sombras também ajudam utilizadores com deficiência visual a distinguir os limites dos elementos. No entanto, o uso excessivo de sombras (3+ níveis num ecrã) aumenta a carga cognitiva e prejudica a perceção.

Sombras no iOS: CALayer e SwiftUI

No iOS, as sombras são implementadas através das propriedades de CALayer: shadowColor define a cor da sombra, shadowOffset — deslocamento em CGSize (x, y), shadowRadius — raio de desfoque, shadowOpacity — opacidade de 0 a 1. Para desempenho, também é recomendado definir shadowPath — um UIBezierPath que descreve a forma da sombra, para que a Core Animation não a calcule automaticamente.

swift
// UIKit: configuração de sombra via CALayer
import UIKit

let cardView = UIView()
cardView.backgroundColor = .systemBackground
cardView.layer.cornerRadius = 12

// Configuração de sombra
cardView.layer.shadowColor = UIColor.black.cgColor
cardView.layer.shadowOpacity = 0.15
cardView.layer.shadowOffset = CGSize(width: 0, height: 4)
cardView.layer.shadowRadius = 8

"> Otimização: shadowPath explícito
cardView.layer.shadowPath = UIBezierPath(
    roundedRect: cardView.bounds,
    cornerRadius: 12
).cgPath

No SwiftUI, as sombras são definidas através do modificador .shadow() com parâmetros color, radius, x, y. O SwiftUI aplica automaticamente shadowPath e gere o desempenho de renderização. Para sombras avançadas (sombras internas, múltiplas sombras), use overlay() com LinearGradient.

swift
// SwiftUI: sombra via modificador shadow
import SwiftUI

VStack {
    Text("Cartão com sombra")
        .padding()
        .background(Color.white)
        .cornerRadius(16)
        .shadow(
            color: .black.opacity(0.15),
            radius: 10,
            x: 0,
            y: 4
        )
}

Desempenho de sombras no iOS: se shadowPath não for definido, a Core Animation calcula a sombra com base na forma da camada a cada fotograma, o que pode causar lentidão durante a animação. Para elementos estáticos, defina sempre shadowPath. Para elementos animados, use shouldRasterize = true na CALayer para armazenar em cache a sombra numa camada separada. No SwiftUI, a rasterização é gerida através de .drawingGroup().

Sombras no Android: elevation e sombras personalizadas

No Android, as sombras no Material Design são implementadas através de elevation — uma propriedade View que define a altura do elemento na coordenada z. O sistema renderiza automaticamente uma sombra com base em elevation e outlineProvider (contorno do elemento). Quanto maior a elevation, maior e mais desfocada é a sombra. Para Views que não herdam do Material Design (ex.: AppCompat), as sombras só funcionam com aceleração de hardware ativada.

xml
<!-- XML: elevation através de atributos -->
<androidx.cardview.widget.CardView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:cardCornerRadius="12dp"
    app:cardElevation="6dp">
    <!-- Conteúdo do cartão -->
</androidx.cardview.widget.CardView>

Para sombras personalizadas no sistema de Views do Android, use OutlineProvider. ViewOutlineProvider permite definir uma forma arbitrária através de outline.setRoundRect() ou outline.setPath(). Sem OutlineProvider, a sombra é renderizada com base na forma retangular da View, não considerando o arredondamento dos cantos.

kotlin
// Kotlin: OutlineProvider personalizado para sombra
import android.graphics.Outline
import android.view.View
import android.view.ViewOutlineProvider

val myView: View = findViewById(R.id.myView)
myView.outlineProvider = object : ViewOutlineProvider() {
    override fun getOutline(view: View, outline: Outline) {
        outline.setRoundRect(
            0, 0, view.width, view.height,
            12f  // raio do canto
        )
    }
}
myView.elevation = 8f  // altura da sombra em px
myView.translationZ = 4f  // altura adicional ao pressionar

No Jetpack Compose, as sombras são geridas através de Modifier.shadow() e elevation nos componentes Card e Surface. Modifier.shadow() aceita elevation e shape. Ao contrário do sistema de Views, o Compose renderiza sombras no seu próprio pipeline de renderização, proporcionando um comportamento mais previsível em todas as versões do Android.

kotlin
// Jetpack Compose: sombra via Modifier.shadow
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

Card(
    modifier = Modifier.shadow(
        elevation = 6.dp,
        shape = RoundedCornerShape(12.dp),
        clip = false
    ),
    colors = CardDefaults.cardColors(containerColor = Color.White)
) {
    Text("Card com sombra personalizada")
}

Recomendações para uso de sombras

O uso correto de sombras melhora a perceção da interface, enquanto o uso incorreto cria ruído visual e degrada o desempenho. O Material Design define cinco níveis de elevation: 0 dp (sem sombra), 1–4 dp (botões, chips), 6–12 dp (cartões, menus), 16–24 dp (diálogos, bottom sheets), 24+ dp (janelas modais, FAB).

NívelElevationElementosCaracterística da sombra
00 dpTexto, ícones, fundoSem sombra, camada plana
11–4 dpBotões, campos de entradaSombra leve, pequeno deslocamento
26–12 dpCartões, SnackbarSombra moderada, desfoque notável
316–24 dpDiálogos, menusSombra profunda, grande desfoque
424+ dpJanelas modaisSombra máxima, elemento flutua

Boas práticas: (1) não use sombras para elementos que não devem atrair atenção (fundos, divisores), (2) a altura da sombra deve corresponder à importância do elemento — quanto mais importante, mais alta, (3) ao pressionar um botão, diminua a elevation com animação para feedback tátil, (4) evite sombras em fundos escuros — use overlay (clarear/escurecer) em vez de sombra. No Material You (Android 12+), as sombras adaptam-se ao tema: em fundos escuros, a elevation é substituída por uma camada de cor (surface tint).

Sombras no Flutter: BoxShadow e PhysicalModel

No Flutter, as sombras são implementadas através de BoxShadow dentro de BoxDecoration. BoxShadow aceita color, offset, blurRadius e spreadRadius. O Flutter suporta múltiplas sombras: passar uma lista de BoxShadow permite criar efeitos complexos — por exemplo, uma sombra externa + destaque interno. PhysicalModel é uma alternativa que simula uma sombra física baseada na forma (BeveledRectangleBorder, CircleBorder).

dart
// Flutter: sombra via BoxDecoration + BoxShadow
import 'package:flutter/material.dart';

Container(
    decoration: BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.circular(12.0),
        boxShadow: [
            BoxShadow(
                color: Colors.black.withOpacity(0.15),
                offset: Offset(0, 4),
                blurRadius: 8.0,
                spreadRadius: 0,
            ),
        ],
    ),
    child: Text('Contentor com sombra'),
)

// PhysicalModel para sombra física
PhysicalModel(
    color: Colors.white,
    elevation: 6.0,
    shadowColor: Colors.black.withOpacity(0.2),
    borderRadius: BorderRadius.circular(12.0),
    child: Text('Modelo físico com sombra'),
)

Desempenho: BoxShadow com múltiplas sombras pode causar repintura a cada alteração. Para elementos estáticos, use PhysicalModel — armazena em cache a sombra numa camada separada (RepaintBoundary). No Flutter 3.16+, é suportada elevation do Material 3 com sombras adaptativas, que mudam de cor e desfoque conforme o tema (claro/escuro).

Perguntas frequentes

Como elevation difere de shadow?

Elevation é a altura numérica de um elemento na coordenada z, enquanto shadow (sombra) é o efeito visual criado por essa altura. No Android, elevation é uma propriedade View que gera automaticamente uma sombra. No design, elevation e shadow são frequentemente usados de forma intercambiável, mas tecnicamente elevation é a causa e shadow é o efeito.

Por que a sombra não aparece no Android?

Verifique: (1) a View tem elevation maior que 0, (2) outlineProvider está definido (se a View não for da biblioteca Material), (3) a aceleração de hardware está ativada (android:hardwareAccelerated="true" no manifesto). CardView gere automaticamente outlineProvider. Para Views personalizadas, chame view.outlineProvider = ViewOutlineProvider.BACKGROUND.

Como criar uma sombra interna (inner shadow) no iOS?

CALayer não suporta sombras internas diretamente. Use uma combinação: CAGradientLayer com cor preta e transparência dentro de uma máscara, ou sobreponha uma UIImageView com uma sombra interna rasterizada. No SwiftUI, a sombra interna é implementada através de overlay com LinearGradient e blendMode(.multiply).

Como animar a sombra ao pressionar um botão?

No Android, use translationZ para animação: em repouso elevation = 2 dp, ao pressionar translationZ = 4 dp (altura total 6 dp). No iOS, anime shadowOffset e shadowRadius simultaneamente com a transformação do botão. No SwiftUI, use withAnimation com alteração de elevation através de Modifier.shadow(). No Flutter, use AnimatedContainer com alteração de BoxShadow.

Quantas sombras podem ser usadas num ecrã?

O Material Design recomenda não mais de três níveis de elevation num ecrã. Se houver mais elementos com sombra, agrupe-os com a mesma altura. O número excessivo de sombras cria ruído visual e reduz o desempenho de renderização em dispositivos de gama média e baixa.

Resumo

  • Shadow (sombra) é um efeito visual de profundidade baseado na elevation do elemento na coordenada z.
  • No iOS, as sombras são configuradas através de CALayer: shadowColor, shadowOffset, shadowRadius, shadowOpacity.
  • No Android, as sombras são geridas através de elevation e OutlineProvider para forma personalizada.
  • O Material Design define cinco níveis de elevation: 0, 1–4, 6–12, 16–24 e 24+ dp.
  • Jetpack Compose usa Modifier.shadow() e elevation em Card/Surface para gestão de sombras.
  • O Flutter implementa sombras através de BoxShadow (BoxDecoration) e PhysicalModel (sombra física).
  • Otimização: defina shadowPath (iOS), outlineProvider (Android), use PhysicalModel (Flutter).

Vamos desenvolver um aplicativo móvel chave na mão

A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.

Discutir o projeto

Leia também