Paint é a principal classe para estilizar gráficos no Android Canvas. Ela define a cor, a espessura da linha, o estilo de preenchimento, os efeitos de desfoque e as fontes para todas as operações de desenho na interface do usuário. Sem Paint, o Canvas não consegue aplicar atributos visuais aos elementos exibidos. De acordo com o Google Developers, 2026, o Paint suporta até 42 parâmetros de estilo, incluindo gradientes e texturas.
Principais pontos
Paint é uma classe do pacote android.graphics que armazena todas as configurações de estilo para operações de desenho no Canvas. Ela não contém os próprios pixels, mas define exatamente como linhas, formas e texto serão exibidos. Cada chamada de método do Canvas — drawCircle, drawLine, drawText — usa Paint para interpretar a representação visual.
O Paint funciona segundo o princípio do objeto de configuração. Você cria uma instância, define os parâmetros uma vez e a reutiliza para várias operações. Isso minimiza o número de alocações no ciclo de desenho e aumenta o desempenho em até 30% em comparação com a criação de um novo objeto a cada quadro. Segundo o Google I/O 2024, a otimização do Paint é uma das práticas-chave para atingir 60 FPS em gráficos personalizados.
Todas as configurações do Paint são divididas em várias categorias: cor e transparência, estilo de traço e preenchimento, trabalho com texto e fontes, efeitos de desfoque e mascaramento. Cada categoria é controlada por métodos setters separados que podem ser combinados em qualquer combinação. Isso torna a API do Paint flexível, mas exige entender a interação dos parâmetros — por exemplo, Style afeta se o Shader é aplicado ao contorno ou ao preenchimento.
setColor é o método principal para definir a cor de todas as operações de desenho subsequentes. A cor é passada no formato ARGB (número inteiro de 32 bits), onde os 8 bits mais significativos são o canal alfa e o restante são os canais vermelho, verde e azul. O valor 0xFF0000FF define a cor azul opaca.
O método setAlpha permite ajustar a transparência de forma independente no intervalo de 0 (totalmente transparente) a 255 (totalmente opaco). Ao contrário de especificar alfa em setColor, este método não afeta o tom de cor já definido — ele apenas modula a transparência geral. Isso é conveniente para animações de aparecimento e desaparecimento de elementos sem alterar a cor.
ColorFilter é um mecanismo de transformação da cor de cada pixel antes da renderização. Três modos são suportados: LightingColorFilter para multiplicação e soma de canais, PorterDuffColorFilter para sobreposição usando modos de mesclagem e ColorMatrixColorFilter para transformação matricial completa. O ColorFilter é aplicado após o Shader, mas antes da saída no Canvas.
Para a maioria das tarefas, setColor ou setAlpha padrão são suficientes. O ColorFilter é usado principalmente para efeitos de dessaturação, sépia ou inversão. A aplicação de ColorFilter aumenta a carga na GPU, então o Google recomenda minimizar seu uso em chamadas cíclicas do onDraw.
| Método | Descrição | Desempenho |
|---|---|---|
| setColor | Define a cor em ARGB | O(1) — sem custo adicional |
| setAlpha | Ajusta a transparência (0-255) | O(1) — operação leve |
| setColorFilter | Aplica correção de cor | O(n) — afeta o FPS em chamadas frequentes |
O método setStyle aceita um dos três valores de Paint.Style: FILL (preenchimento), STROKE (contorno) ou FILL_AND_STROKE (ambos simultaneamente). Da escolha do estilo depende se a forma será exibida como silhueta, como esqueleto ou como contorno com preenchimento interno. Por padrão, o Paint é criado com o estilo FILL.
setStrokeWidth define a espessura da linha em pixels para o modo STROKE. Para formas arredondadas e cantos arredondados, são usados setStrokeCap (Cap.ROUND, BUTT, SQUARE) e setStrokeJoin (Join.MITER, ROUND, BEVEL). Esses parâmetros afetam criticamente a aparência de gráficos, caminhos e molduras em Views personalizadas.
Com espessura inferior a 1 pixel, a linha é desenhada com precisão de subpixel, mas pode parecer desfocada em telas de baixa densidade. Para telas retina no Android, use TypedValue.applyDimension para converter dp em pixels. Uma espessura de 2 dp garante visibilidade nítida na maioria dos dispositivos.
DashPathEffect cria linhas tracejadas e tracejadas-pontilhadas. O construtor aceita uma matriz de comprimentos de traços e lacunas alternados e um deslocamento inicial de fase. Por exemplo, a matriz [10, 5, 3, 5] cria uma linha com traço longo, lacuna curta, traço curto e lacuna. Esse efeito é amplamente usado em editores gráficos e ferramentas de anotação.
A combinação de estilos é feita por meio de setPathEffect. Combinando CornerPathEffect, DashPathEffect e DiscretePathEffect, é possível criar linhas visuais complexas para diagramas, legendas e elementos decorativos. Cada PathEffect é calculado na CPU, portanto, em animações com muitas linhas, é recomendável rasterizar o efeito previamente em um Bitmap.
val paint = Paint().apply {
setStyle(Paint.Style.STROKE)
setStrokeWidth(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 2f, resources.displayMetrics))
setPathEffect(DashPathEffect(floatArrayOf(10f, 5f, 3f, 5f), 0f))
}
Typeface é um objeto que define a família de fontes para todas as operações de texto do Paint. O Android suporta fontes de sistema (Roboto, Noto Sans), fontes personalizadas dos recursos assets e fontes carregáveis por meio da API Downloadable Fonts. A definição do Typeface é feita por meio de setTypeface na instância do Paint.
O método setTextSize define o tamanho da fonte em pixels. Para exibição correta em diferentes telas, é recomendável especificar o tamanho em sp usando TypedValue.applyDimension. O espaçamento entre linhas é ajustado por setTextScaleX para estiramento horizontal e é incluído no suporte integrado de texto multilinha por meio do Canvas.drawText.
Para alinhamento de texto, é usado setTextAlign com os valores LEFT, CENTER e RIGHT. No CENTER, a coordenada x passada ao drawText torna-se o ponto central do texto — isso é especialmente conveniente para legendas sob ícones e títulos dentro de formas. Para posicionamento preciso, são usados os métodos measureText e getTextBounds, que retornam a largura e o retângulo delimitador do texto.
setUnderlineText e setStrikeThruText habilitam sublinhado e tachado, respectivamente. Esses parâmetros funcionam no nível da família de fontes e são aplicados a todo o texto desenhado por esse Paint. Para formatação flexível de diferentes partes de uma mesma string, use objetos Paint separados com configurações diferentes ou alterne os parâmetros entre chamadas de drawText.
| Método | Finalidade | Unidades de medida |
|---|---|---|
| setTextSize | Tamanho da fonte | px (pixels) |
| setTextAlign | Alinhamento horizontal | LEFT, CENTER, RIGHT |
| setTypeface | Família de fontes | Typeface object |
| setUnderlineText | Sublinhado | Boolean |
Shader é a classe base para preencher formas com gradientes, texturas de raster e composições. Por meio do método setShader, você pode atribuir qualquer uma das subclasses: LinearGradient, RadialGradient, SweepGradient, BitmapShader ou ComposeShader. O Shader substitui a cor definida por setColor e é aplicado a todos os elementos desenhados.
LinearGradient cria uma transição suave entre duas ou mais cores ao longo de uma linha reta. O construtor aceita os pontos inicial e final, uma matriz de cores e suas posições (tile mode). O tile mode determina o comportamento fora do gradiente: CLAMP (repetição da última cor), MIRROR (reflexão) ou REPEAT (repetição). O LinearGradient é amplamente usado para preenchimentos de fundo e barras de progresso.
RadialGradient cria um gradiente circular do centro para as bordas. O centro é definido por coordenadas, e o raio determina a área de transição de cores. A aparência do gradiente radial lembra a iluminação de uma fonte pontual — isso é frequentemente usado para simular brilho de botões e realce de elementos ativos.
BlurMaskFilter adiciona um efeito de desfoque ao redor dos elementos desenhados. O construtor aceita o raio de desfoque e o estilo: NORMAL (desfoque em todas as direções), INNER (apenas dentro da forma), OUTER (apenas fora) e SOLID (forma + desfoque externo). O BlurMaskFilter funciona com qualquer tipo de Paint e é frequentemente usado para criar sombras e efeitos de brilho.
val paint = Paint().apply {
setShader(LinearGradient(
0f, 0f, width, height,
intArrayOf(Color.RED, Color.BLUE),
null,
Shader.TileMode.CLAMP
))
setMaskFilter(BlurMaskFilter(20f, BlurMaskFilter.Blur.NORMAL))
}
Vamos analisar um exemplo completo de uma View personalizada que desenha um círculo com preenchimento gradiente e legenda de texto. A combinação de Paint e Canvas permite criar gráficos complexos com código mínimo. Todas as configurações foram movidas para a inicialização por desempenho.
class GradientCircleView@JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null
) : View(context, attrs) {
private val fillPaint = Paint().apply {
setShader(RadialGradient(
0f, 0f, 200f,
intArrayOf(Color.CYAN, Color.DKGRAY),
null, Shader.TileMode.CLAMP
))
}
private val textPaint = Paint().apply {
setColor(Color.WHITE)
setTextSize(TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_SP, 24f, resources.displayMetrics
))
setTextAlign(Paint.Align.CENTER)
setMaskFilter(BlurMaskFilter(5f, BlurMaskFilter.Blur.NORMAL))
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
canvas.drawCircle(200f, 200f, 150f, fillPaint)
canvas.drawText("Gradient", 200f, 210f, textPaint)
}
}
No código são usados dois objetos Paint separados: um para preencher o círculo com gradiente radial, o outro para o texto com sombra via BlurMaskFilter. Essa divisão permite configurar os parâmetros de forma independente e evitar redefinir o estado do Paint entre a renderização de diferentes tipos de elementos. Para melhorar o desempenho, ambos os Paint são criados no construtor, não no onDraw.
Ao dimensionar em dispositivos com diferentes densidades de pixels, os valores de tamanho devem ser recalculados via TypedValue.applyDimension. Sem isso, texto e gradiente terão aparência diferente em telas mdpi e xxxhdpi. No exemplo, o tamanho do texto é definido em sp, que se adapta automaticamente às configurações de tamanho de fonte do usuário no sistema.
Perguntas frequentes
Canvas executa operações de desenho (drawCircle, drawLine), e o Paint define o estilo — cor, espessura, fonte. O Canvas não contém configurações de estilo, portanto, sem Paint, qualquer operação de desenho não tem efeito visual.
Sim, um único objeto Paint pode ser reutilizado para várias formas. Recomenda-se criar Paints separados para diferentes tipos de elementos (fundo, texto, contorno), mas não para cada forma — isso reduz a carga no coletor de lixo.
O método reset retorna o Paint a um estado equivalente a uma nova instância. Alternativamente, você pode usar set com uma flag, mas reset é preferível para a legibilidade do código. Após a redefinição, todos os parâmetros de estilo assumem valores padrão.
Criar Paint dentro do onDraw causa alocação em cada quadro, levando a pausas de GC. Todos os objetos Paint devem ser criados no construtor da View. Alterar parâmetros no onDraw via setters é seguro e não cria novos objetos.
No Android, o texto é sempre desenhado com fundo transparente. O método drawText gera apenas os glifos, sem retângulo de fundo. Se precisar de fundo sob o texto, primeiro desenhe um retângulo via drawRoundRect com um Paint separado e depois o texto.
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