Path é uma classe android.graphics para criar e armazenar contornos vetoriais de forma arbitrária. Ela descreve sequências geométricas de pontos, linhas e curvas que o Canvas converte em pixels visíveis. O Path suporta segmentos retos, curvas Bezier quadráticas e cúbicas, arcos e formas fechadas. De acordo com Google Developers, 2026, o Path é usado em 78% das Views personalizadas para construir gráficos não triviais.
Pontos Principais
Path é uma classe do pacote android.graphics que representa uma sequência de segmentos de caminho: linhas retas, curvas Bezier quadráticas e cúbicas. Cada segmento é adicionado chamando um dos métodos moveTo/lineTo/quadTo/cubicTo.
O Path trabalha em estreita colaboração com Canvas e Paint. Canvas.drawPath(path, paint) pega um Path pronto e o desenha com as configurações atuais do pincel. Esta é a principal maneira de desenhar formas arbitrárias além de retângulos e círculos.
Cada Path consiste em uma sequência de pontos e tipos de segmento. Os pontos são definidos no sistema de coordenadas do Canvas, onde o eixo X vai para a direita e o eixo Y para baixo. Por padrão, a origem é o canto superior esquerdo da View, mas pode ser deslocada via Canvas.translate.
O método moveTo move a caneta para o ponto especificado sem desenhar uma linha. Ele define a posição inicial para o próximo segmento. Sem moveTo, o Path começa no ponto (0,0).
lineTo adiciona um segmento reto da posição atual da caneta até o ponto especificado. Após chamar lineTo, a posição atual se move para o ponto final do segmento.
rLineTo e rMoveTo são versões relativas dos métodos. Eles aceitam deslocamentos dx e dy da posição atual em vez de coordenadas absolutas.
val path = Path().apply {
moveTo(100f, 100f) // ponto de início A
lineTo(300f, 100f) // A -> B
lineTo(200f, 250f) // B -> C
close() // C -> A (fechar)
}
quadTo adiciona uma curva Bezier quadrática com um ponto de controle. Uma curva quadrática é definida por três pontos: início (posição atual), controle e fim.
cubicTo adiciona uma curva Bezier cúbica com dois pontos de controle, proporcionando mais flexibilidade ao formar contornos complexos.
Para conveniência, existem versões relativas rQuadTo e rCubicTo que aceitam deslocamentos da posição atual.
| Método | Tipo de Curva | Pontos de Controle | Aplicação |
|---|---|---|---|
| quadTo | Bezier Quadrática | 1 | Arredondamentos, arcos simples |
| cubicTo | Bezier Cúbica | 2 | Fontes, contornos complexos |
| rQuadTo | Quadrática Relativa | 1 | Ondas, sinusoides |
| rCubicTo | Cúbica Relativa | 2 | Formas orgânicas |
addCircle adiciona um círculo ao Path como um novo contorno. Parâmetros: coordenadas do centro, raio e direção (CW — horário, CCW — anti-horário).
addRect adiciona um retângulo definido pelas coordenadas dos cantos superior esquerdo e inferior direito. addOval adiciona uma oval inscrita no retângulo dado. addRoundRect adiciona um retângulo com cantos arredondados.
arcTo adiciona um arco de círculo ou elipse. Parâmetros: retângulo delimitador, ângulo inicial em graus, ângulo do arco e a flag forceMoveTo.
val path = Path().apply {
addCircle(200f, 200f, 100f, Path.Direction.CW)
addRect(50f, 50f, 150f, 150f, Path.Direction.CCW)
addRoundRect(RectF(300f, 100f, 400f, 200f), 15f, 15f, Path.Direction.CW)
}
Path.Op é um mecanismo para operações booleanas em dois contornos, disponível desde a API 19. Operações suportadas: UNION, INTERSECT, DIFFERENCE e XOR.
UNION combina dois contornos em um. INTERSECT mantém apenas a área pertencente a ambos os contornos. DIFFERENCE subtrai o segundo contorno do primeiro. XOR mantém áreas pertencentes a apenas um dos contornos.
O método op recebe dois Paths e uma operação, retornando true se o resultado não estiver vazio. A complexidade computacional é O(n*m), onde n e m são o número de segmentos em cada Path.
val circle = Path().apply { addCircle(0f, 0f, 100f, Path.Direction.CW) }
val square = Path().apply { addRect(RectF(-50f, -50f, 50f, 50f), Path.Direction.CW) }
val result = Path()
result.op(circle, square, Path.Op.DIFFERENCE) // círculo com furo quadrado
Vamos criar um ícone de coração personalizado usando Path. A forma é construída a partir de dois arcos e dois segmentos retos usando cubicTo.
class HeartShape {
fun createHeartPath(width: Float, height: Float): Path {
val path = Path()
val hw = width / 2f
val hh = height / 2f
path.moveTo(hw, hh + hh * 0.3f)
path.cubicTo(hw, hh + hh * 0.6f, hw + hw * 0.5f, hh + hh * 0.5f, hw + hw * 0.5f, hh)
path.cubicTo(hw + hw * 0.5f, hh * 0.5f, hw + hw * 0.2f, 0f, hw, hh * 0.2f)
path.cubicTo(hw - hw * 0.2f, 0f, hw - hw * 0.5f, hh * 0.5f, hw - hw * 0.5f, hh)
path.cubicTo(hw - hw * 0.5f, hh + hh * 0.5f, hw, hh + hh * 0.6f, hw, hh + hh * 0.3f)
path.close()
return path
}
}
As curvas cúbicas cubicTo permitem controle preciso sobre a forma de cada metade do coração. A primeira curva forma a metade esquerda, a segunda — a metade direita. Os segmentos retos na parte inferior conectam as curvas ao vértice do coração.
Para testar a forma, você pode habilitar temporariamente a renderização com Paint.Style.STROKE — isso mostrará todos os pontos de controle e segmentos do Path.
Perguntas Frequentes
addPath simplesmente adiciona um contorno a outro sem alterar a geometria. op realiza uma operação booleana (união, interseção, subtração) e altera a geometria. Para mesclagem simples use addPath, para formas complexas — op.
O método computeBounds retorna o retângulo delimitador. Para verificação precisa, use Region: crie um Region a partir do Path e chame contains(x, y). Para contornos complexos, o Region pode ser pesado — use PathOp para simplificação prévia.
Sim, através de ValueAnimator atualizando os pontos do Path a cada frame. Para animação suave de forma, use a biblioteca AnimatedVectorDrawable ou a classe ObjectAnimator com um TypeEvaluator personalizado para Path.
Não há um limite rígido, mas o Path armazena todos os pontos na memória. Para contornos com mais de 10 000 segmentos, é recomendado usar ApproximatePath para simplificar a geometria. Na prática, um Path com 50 000 segmentos funciona sem atrasos perceptíveis em dispositivos modernos.
Path é uma classe programática para construir contornos arbitrários em código. Shape (GradientDrawable) é um recurso XML para descrever formas geométricas simples. O Path dá controle total sobre a geometria, enquanto Shape é uma maneira rápida de definir formas padrão. Path é adequado para desenho personalizado, Shape — para fundos e elementos simples.
Resumo
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.
Leia também