Paint in Android: what it is, configuration methods and how it works

Author: IT Sectr Published: 2026-07-21 Reading time: 9 min

Paint is the main class for styling graphics in Android Canvas. It defines color, line thickness, fill style, blur effects and fonts for all drawing operations in the user interface. Without Paint, Canvas cannot apply visual attributes to displayed elements. According to Google Developers, 2026, Paint supports up to 42 style parameters, including gradients and textures.

Key Takeaways

  • Paint is a styling object for Canvas, containing all visual drawing settings.
  • setColor and setAlpha control the color and transparency of lines and fills.
  • Style determines whether a stroke, fill, or both are drawn simultaneously.
  • Shader allows applying gradients, bitmap textures and compositing.
  • Typeface sets the font for text with support for all Android system typefaces.

What is Paint in Android?

Paint is a class from the android.graphics package that stores all style settings for drawing operations on Canvas. It does not contain pixels itself, but determines how lines, shapes and text will look. Each Canvas method call — drawCircle, drawLine, drawText — uses Paint to interpret the visual representation.

Paint works on the principle of a configuration object. You create an instance, set parameters once and reuse it for multiple operations. This minimizes allocations in the drawing loop and improves performance by up to 30% compared to creating a new object every frame. According to Google I/O 2024, Paint optimization is one of the key practices for achieving 60 FPS in custom graphics.

All Paint settings are divided into several categories: color and transparency, stroke and fill style, text and font handling, blur and masking effects. Each category is controlled by separate setter methods that can be combined in any combination. This makes the Paint API flexible, but requires understanding how parameters interact — for example, Style affects whether Shader is applied to the stroke or to the fill.

Color and transparency in Paint

setColor is the main method for setting the color for all subsequent drawing operations. The color is passed in ARGB format (32-bit integer), where the high 8 bits are the alpha channel, and the rest are the red, green and blue channels. The value 0xFF0000FF sets an opaque blue color.

Alpha channel management

The setAlpha method allows independently adjusting transparency in the range from 0 (fully transparent) to 255 (fully opaque). Unlike specifying alpha in setColor, this method does not affect the already set color tone — it only modulates overall transparency. This is convenient for animating element appearance and disappearance without changing colors.

ColorFilter for color correction

ColorFilter is a mechanism for transforming the color of each pixel before rendering. Three modes are supported: LightingColorFilter for channel multiplication and addition, PorterDuffColorFilter for overlay using blend modes, and ColorMatrixColorFilter for full matrix transformation. ColorFilter is applied after Shader but before output to Canvas.

For most tasks, standard setColor or setAlpha is sufficient. ColorFilter is primarily used for desaturation, sepia or inversion effects. Using ColorFilter increases GPU load, so Google recommends minimizing its use in cyclic calls to onDraw.

MethodDescriptionPerformance
setColorSets color in ARGBO(1) — no overhead
setAlphaAdjusts transparency (0-255)O(1) — lightweight operation
setColorFilterApplies color correctionO(n) — affects FPS with frequent calls

Style and line thickness

The setStyle method accepts one of three Paint.Style values: FILL, STROKE or FILL_AND_STROKE. The choice of style determines whether a shape will be displayed as a silhouette, a wireframe, or a stroke with inner fill. By default, Paint is created with the FILL style.

Line thickness and joins

setStrokeWidth sets the line thickness in pixels for STROKE mode. For rounded shapes and rounded corners, setStrokeCap (Cap.ROUND, BUTT, SQUARE) and setStrokeJoin (Join.MITER, ROUND, BEVEL) are used. These parameters critically affect the appearance of graphs, paths and borders in custom Views.

At thicknesses less than 1 pixel, a line is drawn with subpixel precision but may appear blurry on low-density screens. For Android Retina displays, use TypedValue.applyDimension to convert dp to pixels. A thickness of 2 dp provides clear visibility on most devices.

Dash patterns (DashPathEffect)

DashPathEffect creates dashed and dash-dotted lines. The constructor accepts an array of alternating dash and gap lengths and an initial phase offset. For example, the array [10, 5, 3, 5] creates a line with a long dash, short gap, short dash and gap. This effect is actively used in graphic editors and annotation tools.

Combining styles is done through setPathEffect. By combining CornerPathEffect, DashPathEffect and DiscretePathEffect, you can create complex visual lines for charts, labels and decorative elements. Each PathEffect is computed on the CPU, so in animations with many lines, it is recommended to pre-rasterize the effect into a Bitmap.

kotlin
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))
}

Fonts and text rendering

Typeface is an object that defines the font typeface for all Paint text operations. Android supports system fonts (Roboto, Noto Sans), custom fonts from assets resources and downloadable fonts via the Downloadable Fonts API. Typeface is set using setTypeface on a Paint instance.

Text size and line spacing

The setTextSize method sets the font size in pixels. For correct display on different screens, it is recommended to specify the size in sp using TypedValue.applyDimension. Line spacing is adjusted using setTextScaleX for horizontal stretching and is supported by built-in MultiLine text via Canvas.drawText.

For text alignment, setTextAlign is used with values LEFT, CENTER and RIGHT. With CENTER, the x coordinate passed to drawText becomes the center point of the text — this is especially convenient for labels under icons and headings inside shapes. For precise positioning, the measureText and getTextBounds methods are used, returning the width and bounding rectangle of the text.

Underline and strikethrough

setUnderlineText and setStrikeThruText enable underlining and strikethrough respectively. These parameters work at the typeface level and apply to all text drawn by this Paint. For flexible formatting of different parts of the same string, use separate Paint objects with different settings or switch parameters between drawText calls.

MethodPurposeUnits
setTextSizeFont sizepx (pixels)
setTextAlignHorizontal alignmentLEFT, CENTER, RIGHT
setTypefaceFont typefaceTypeface object
setUnderlineTextUnderlineBoolean

Gradients and advanced effects

Shader is the base class for filling shapes with gradients, bitmap textures and compositing. Through the setShader method, you can assign any of its subclasses: LinearGradient, RadialGradient, SweepGradient, BitmapShader or ComposeShader. Shader replaces the color set by setColor and is applied to all drawn elements.

Linear and radial gradients

LinearGradient creates a smooth transition between two or more colors along a straight line. The constructor accepts start and end points, an array of colors and their positions (tile mode). Tile mode determines behavior beyond the gradient: CLAMP (repeat last color), MIRROR (reflection) or REPEAT (repeat). LinearGradient is actively used for background fills and progress bars.

RadialGradient creates a circular gradient from the center to the edges. The center is specified by coordinates, the radius defines the color transition area. The appearance of a radial gradient resembles lighting from a point source — this is often used to simulate button glow and highlight active elements.

Blur and shadows (BlurMaskFilter)

BlurMaskFilter adds a blur effect around drawn elements. The constructor accepts a blur radius and a style: NORMAL (blur in all directions), INNER (only inside the shape), OUTER (only outside) and SOLID (shape + outer blur). BlurMaskFilter works with any Paint types and is often used to create shadows and glow effects.

kotlin
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))
}

Example of using Paint with Canvas

Let us consider a complete example of a custom View that draws a circle with a gradient fill and a text label. The combination of Paint and Canvas allows creating complex graphics with minimal code. All settings are moved to initialization for performance.

kotlin
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)
    }
}

The code uses two separate Paint objects: one for filling the circle with a radial gradient, and the second for text with a shadow via BlurMaskFilter. This separation allows independently configuring parameters and avoiding Paint state reset between drawing different types of elements. For performance improvement, both Paint objects are created in the constructor, not in onDraw.

When scaling on devices with different pixel densities, size values should be recalculated using TypedValue.applyDimension. Without this, text and gradients will look different on mdpi and xxxhdpi screens. In the example, text size is specified in sp, which automatically adapts to the user system font size settings.

Frequently asked questions

How is Paint different from Canvas?

Canvas performs drawing operations (drawCircle, drawLine), while Paint defines the style — color, thickness, font. Canvas does not contain style settings, so without Paint any drawing operation has no visual effect.

Can one Paint be used for different shapes?

Yes, a single Paint object can be reused for many shapes. It is recommended to create separate Paint objects for different types of elements (background, text, stroke), but not for each shape — this reduces garbage collector load.

How to reset Paint to default settings?

The reset method returns Paint to a state equivalent to a new instance. Alternatively, you can use set with a flag, but reset is preferable for code readability. After resetting, all style parameters take default values.

Does Paint affect performance in onDraw?

Creating Paint inside onDraw causes allocation in every frame, leading to GC freezes. All Paint objects should be created in the View constructor. Changing parameters in onDraw via setters is safe and does not create new objects.

How to make a transparent background for text in Paint?

Text in Android is always drawn with a transparent background. The drawText method only outputs glyphs, without a background rectangle. If a background under the text is needed, first draw a rectangle using drawRoundRect with a separate Paint, and then the text.

Summary

  • Paint is a configuration class for styling graphics on Canvas, defining color, thickness, font and effects.
  • setColor and setAlpha control color and transparency with minimal overhead.
  • Style (FILL, STROKE, FILL_AND_STROKE) determines whether a stroke, fill or both are drawn.
  • Typeface and setTextSize handle fonts with support for Downloadable Fonts and screen adaptation.
  • Shader — LinearGradient, RadialGradient, BitmapShader — adds gradients and textures.
  • Create Paint in the View constructor, not in onDraw, to prevent GC freezes.
  • Separate Paint by element type: fill, stroke, text — for flexible configuration and code readability.

We will develop a mobile application turnkey

IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.

Discuss the project

Read also