Canvas у Android-у: шта је то, класа Canvas и методе draw

Аутор: IT Sectr Објављено: 2026-07-21 Време читања: 7 мин

Canvas у Android-у — је класа из пакета android.graphics која пружа API за 2D цртање на View. Canvas функционише као платно на којем програмер црта геометријске фигуре, текст, слике и путање помоћу различитих draw* метода. Према Android Developers Documentation (2025), Canvas је основни алат за прилагођено цртање у Android-у и користи се заједно са класом Paint за задавање стилова и боја. Сваки позив onDraw() добија готову инстанцу Canvas повезану са bitmap бафером прегледа.

Главно

  • Canvas — класа за 2D цртање у Android-у, пружа методе drawRect, drawCircle, drawText, drawBitmap и друге
  • Paint — класа која одређује стил цртања: боју, дебљину, попуну, ефекте (сенку, градијент)
  • onDraw(Canvas) — метод View у којем се одвија све цртање кроз добијени Canvas
  • Canvas.save() и restore() — управљање стеком трансформација за угнеждене трансформације координатног система
  • Path — класа за изградњу произвољних контура и кривих, прослеђује се у drawPath(Path, Paint)

Шта је Canvas у Android-у

Canvas — је централна класа 2D графике у Android-у која пружа методе за цртање на равни. Сваки Canvas је повезан са Bitmap — меморијском облашћу у коју се уписују резултати операција цртања. Када се View поново исцртава, систем прослеђује у onDraw() Canvas који је већ повезан са бафером тог View.

Canvas ради у координатном систему где је (0,0) горњи леви угао, оса X иде удесно, оса Y наниже. Све операције цртања користе тренутно стање Canvas-а, укључујући матрицу трансформације, област сечења (clip) и стил Paint. Према Android Documentation (2025), Canvas API укључује преко 30 draw* метода за различите типове графичких примитива.

Canvas и хардверско убрзање

Од Android 3.0 (API 11) Canvas подржава хардверско убрзање кроз DisplayList. У убрзаном режиму, Canvas операције се записују у DisplayList и затим извршавају на GPU-у. Ово даје значајан пораст перформанси, али намеће ограничења: неке Canvas операције (clipPath са не-Path клипом) нису подржане у убрзаном режиму.

Основни методи Canvas за цртање

Canvas пружа скуп метода за цртање основних примитива. Сваки метод прима геометријске параметре и објекат Paint који одређује визуелни стил.

МетодНаменаПример
drawRect()Цртање правоугаоникаcanvas.drawRect(10f, 10f, 100f, 100f, paint)
drawCircle()Цртање кругаcanvas.drawCircle(50f, 50f, 30f, paint)
drawLine()Цртање линијеcanvas.drawLine(0f, 0f, 100f, 100f, paint)
drawText()Цртање текстаcanvas.drawText("Hello", 10f, 20f, paint)
drawBitmap()Цртање сликеcanvas.drawBitmap(bitmap, 0f, 0f, paint)
drawPath()Цртање произвољне путањеcanvas.drawPath(path, paint)
drawOval()Цртање овалаcanvas.drawOval(rectF, paint)
drawArc()Цртање лука или сектораcanvas.drawArc(rectF, 0f, 90f, true, paint)

Сваки метод може бити позван у било ком редоследу — Canvas црта по редоследу позива, постављајући нове елементе преко претходних. За сложене композиције користи се техника вишеслојног цртања са чувањем и враћањем стања Canvas-а.

Класа Paint: подешавање стилова и ефеката

Paint — је класа која одређује како ће Canvas цртати. Без Paint-а, Canvas методи су бескорисни — он задаје боју, дебљину линије, стил попуне, величину текста, ефекте (сенку, градијент, замућење) и режим преклапања.

Paint има кључна својства: color (боја), style (FILL, STROKE или FILL_AND_STROKE), strokeWidth (дебљина линије), textSize (величина текста), isAntiAlias (изглађивање), shader (градијент или слика). Креирање објекта Paint је скупа операција, зато га треба креирати једном и поново користити.

kotlin
private val fillPaint = Paint().apply {
    color = Color.parseColor("#FF6200EE")
    style = Paint.Style.FILL
    isAntiAlias = true
}

private val strokePaint = Paint().apply {
    color = Color.WHITE
    style = Paint.Style.STROKE
    strokeWidth = 4f
    isAntiAlias = true
}

override fun onDraw(canvas: Canvas) {
    super.onDraw(canvas)
    canvas.drawCircle(100f, 100f, 80f, fillPaint)
    canvas.drawCircle(100f, 100f, 80f, strokePaint)
}

У овом примеру се користе два Paint: један за попуну круга љубичастом бојом, други за бели обрис. Подела на fill и stroke је стандардна пракса која омогућава флексибилно управљање изгледом без поновног креирања објеката.

Shader и градијенти

За градијентне попуне Paint прима Shader — подкласе LinearGradient, RadialGradient, SweepGradient. Shader се везује за Paint кроз метод setShader() и одређује како се боја мења по области цртања.

Трансформације Canvas: translate, rotate, scale

Canvas подржава матричне трансформације координатног система: translate() (померање), rotate() (ротација), scale() (скалирање) и skew() (нагињање). Трансформације се акумулирају: сваки наредни позив се примењује на претходне.

Управљање стеком трансформација се врши кроз save() и restore(). save() чува тренутно стање Canvas-а (матрицу, clip) на стек, restore() враћа последње сачувано стање. Између save() и restore() могу бити угнежђене трансформације.

kotlin
override fun onDraw(canvas: Canvas) {
    super.onDraw(canvas)

    canvas.save() // Сачувај почетно стање
    canvas.translate(100f, 100f) // Помери координатни почетак

    // Први квадрат
    canvas.drawRect(0f, 0f, 50f, 50f, fillPaint)

    canvas.save() // Сачувај након померања
    canvas.rotate(45f, 25f, 25f) // Ротирај око центра квадрата

    // Ротирани квадрат
    canvas.drawRect(0f, 0f, 50f, 50f, strokePaint)
    canvas.restore() // Врати након ротације

    canvas.restore() // Врати почетно стање
}

Увек користите save() пре почетка трансформација и restore() након њиховог завршетка. Неуравнотежени save/restore доводе до акумулације матрице и неправилног цртања наредних елемената.

Canvas са Bitmap и Path за сложену графику

За сложену графику, Canvas се комбинује са Bitmap и Path. Bitmap се користи за учитавање слика и кеширање рендерованих оквира. Path — за изградњу произвољних Безијеових кривих, полигона и сложених контура.

Offscreen Bitmap бафер

Техника offscreen-рендеровања: креира се Bitmap, на њему се црта сложена сцена кроз посебан Canvas, а затим се готов Bitmap приказује у onDraw() кроз drawBitmap(). Ово омогућава ажурирање сложене графике без потпуног прецртавања сваког оквира.

kotlin
private var offscreenBitmap: Bitmap? = null
private var offscreenCanvas: Canvas? = null

fun buildOffscreenScene(width: Int, height: Int) {
    offscreenBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
    offscreenCanvas = Canvas(offscreenBitmap)

    // Рендеруј сцену једном
    offscreenCanvas!!.drawColor(Color.WHITE)
    drawGrid(offscreenCanvas!!)
    drawComplexShape(offscreenCanvas!!)
}

override fun onDraw(canvas: Canvas) {
    super.onDraw(canvas)
    offscreenBitmap?.let { canvas.drawBitmap(it, 0f, 0f, null) }
}

Path се користи за изградњу сложених контура: Безијеове криве (quadTo, cubicTo), лукови (arcTo), линије (lineTo). Path може бити затворен (close()) за попуњене фигуре или отворен за линије. Главни методи drawPath() комбинују Path и Paint за коначно цртање.

Оптимизација цртања Canvas

Перформансе Canvas цртања директно утичу на FPS апликације. Главни проблеми: прекомерне алокације у onDraw(), чести invalidate() и неоптимално коришћење хардверског убрзања.

Креирајте објекте ван onDraw()

Paint, Path, Rect, RectF и други објекти треба да се креирају једном у иницијализатору или методи setup(). Свака алокација у onDraw() ствара оптерећење на garbage collector, што доводи до микро-застоја. Изузетак — static или companion object за immutable објекте.

Користите clipRect() за ограничавање области

Ако је велики део View сакривен ван видљиве области (нпр. у ScrollView), користите canvas.clipRect() за ограничавање цртања. Хардверско убрзање у овом случају додатно оптимизује сечење невидљивих пиксела.

kotlin
override fun onDraw(canvas: Canvas) {
    super.onDraw(canvas)

    // Исеци на видљиву област
    canvas.save()
    canvas.clipRect(scrollX, scrollY, scrollX + width, scrollY + height)

    // Рендеруј велику сцену
    renderScene(canvas)
    canvas.restore()
}

Користите View.setLayerType() са LAYER_TYPE_HARDWARE за View са сложеном Canvas графиком која се ретко ажурира. За често ажуриране анимације користите LAYER_TYPE_NONE да бисте избегли скупо ажурирање хардверског слоја. Профилишите кроз GPU Profile Rendering и Android Studio Profiler.

Често постављана питања

Може ли се креирати Canvas без View?

Да, може се креирати Canvas(Bitmap) — конструктор који прима Bitmap. Ово се користи за offscreen-рендеровање: цртате на Bitmap, а затим га приказујете кроз drawBitmap(). Canvas такође може бити креиран из Surface (за SurfaceView) или кроз Picture.

Чиме се разликује Canvas од SurfaceView?

Canvas — је API за цртање на View у UI нити. SurfaceView — је засебан Surface који се може ажурирати из позадинске нити кроз сопствени Canvas (lockCanvas() / unlockCanvasAndPost()). SurfaceView је пожељнији за игре и видео.

Зашто Canvas не црта након трансформације?

Најчешћи узрок су неуравнотежени save() и restore(). Ако након трансформације (translate, rotate) не позовете restore(), Canvas остаје у измењеном координатном систему, а наредни елементи се цртају са померајем. Проверите парове save()/restore().

Како нацртати текст у центру Canvas-а?

Користите Paint.setTextAlign(Paint.Align.CENTER) за хоризонтално поравнање и Paint.getTextBounds() или Paint.descent() / ascent() за вертикално. Центрирање: canvas.drawText(text, centerX, centerY - (ascent + descent) / 2, paint).

Да ли Canvas подржава анимацију?

Canvas сам по себи не анимира — он само црта тренутно стање. Анимација се постиже кроз узастопне позиве invalidate() (или postInvalidateOnAnimation()), сваки пут цртајући нови оквир у onDraw(). За глатке анимације користите ValueAnimator или Choreographer за синхронизацију са Vsync.

Закључак

  • Canvas — централна класа 2D цртања у Android-у, пружа draw* методе за цртање примитива, текста и слика
  • Paint — одређује визуелни стил (боју, дебљину, попуну, шејдере); креира се једном и поново користи
  • save() / restore() — управљање стеком трансформација; свака трансформација треба да буде у пару save/restore
  • Path — изградња произвољних контура и Безијеових кривих за сложену векторску графику
  • Offscreen Bitmap — техника кеширања сложених сцена кроз Canvas(Bitmap) за смањење оптерећења onDraw()
  • Хардверско убрзање — GPU убрзање за Canvas од Android 3.0, намеће ограничења на неке операције (clipPath)
  • Профилисање — GPU Profile Rendering и Android Studio Profiler су обавезни за проналажење уских грла у onDraw()

Развићемо мобилну апликацију под кључ

IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.

Разговарајте о пројекту

Прочитајте такође