Canvas di Android — adalah kelas dari paket android.graphics yang menyediakan API untuk menggambar 2D pada View. Canvas bekerja seperti kanvas, di mana pengembang menggambar bentuk geometris, teks, gambar, dan jalur menggunakan berbagai metode draw*. Menurut Android Developers Documentation (2025), Canvas adalah alat utama untuk menggambar kustom di Android dan digunakan bersama dengan kelas Paint untuk mengatur gaya dan warna. Setiap panggilan onDraw() menerima instance Canvas siap pakai yang terhubung dengan buffer bitmap view.
Poin Utama
Canvas — adalah kelas grafis 2D pusat di Android yang menyediakan metode untuk menggambar pada permukaan. Setiap Canvas terikat pada Bitmap — area memori tempat hasil operasi gambar ditulis. Ketika View digambar ulang, sistem meneruskan ke onDraw() Canvas yang sudah terhubung dengan buffer View ini.
Canvas bekerja dalam sistem koordinat di mana (0,0) adalah sudut kiri atas, sumbu X ke kanan, sumbu Y ke bawah. Semua operasi gambar menggunakan status Canvas saat ini, termasuk matriks transformasi, area klip (clip) dan gaya Paint. Menurut Android Documentation (2025), API Canvas mencakup lebih dari 30 metode draw* untuk berbagai tipe primitif grafis.
Sejak Android 3.0 (API 11) Canvas mendukung percepatan hardware melalui DisplayList. Dalam mode dipercepat, operasi Canvas ditulis ke DisplayList dan kemudian dieksekusi di GPU. Ini memberikan peningkatan kinerja yang signifikan, tetapi memberlakukan batasan: beberapa operasi Canvas (clipPath dengan klip non-Path) tidak didukung dalam mode dipercepat.
Canvas menyediakan serangkaian metode untuk menggambar primitif dasar. Setiap metode menerima parameter geometris dan objek Paint yang menentukan gaya visual.
| Metode | Tujuan | Contoh |
|---|---|---|
| drawRect() | Menggambar persegi panjang | canvas.drawRect(10f, 10f, 100f, 100f, paint) |
| drawCircle() | Menggambar lingkaran | canvas.drawCircle(50f, 50f, 30f, paint) |
| drawLine() | Menggambar garis | canvas.drawLine(0f, 0f, 100f, 100f, paint) |
| drawText() | Menggambar teks | canvas.drawText("Hello", 10f, 20f, paint) |
| drawBitmap() | Menggambar gambar | canvas.drawBitmap(bitmap, 0f, 0f, paint) |
| drawPath() | Menggambar jalur arbitrer | canvas.drawPath(path, paint) |
| drawOval() | Menggambar oval | canvas.drawOval(rectF, paint) |
| drawArc() | Menggambar busur atau sektor | canvas.drawArc(rectF, 0f, 90f, true, paint) |
Setiap metode dapat dipanggil dalam urutan apa pun — Canvas menggambar sesuai urutan panggilan, menempatkan elemen baru di atas yang sebelumnya. Untuk komposisi kompleks digunakan teknik menggambar multi-lapis dengan menyimpan dan memulihkan status Canvas.
Paint — adalah kelas yang menentukan bagaimana Canvas akan menggambar. Tanpa Paint, metode Canvas tidak berguna — ia mengatur warna, ketebalan garis, gaya isian, ukuran teks, efek (bayangan, gradien, blur) dan mode campuran.
Paint memiliki properti kunci: color (warna), style (FILL, STROKE atau FILL_AND_STROKE), strokeWidth (ketebalan garis), textSize (ukuran teks), isAntiAlias (penghalusan), shader (gradien atau gambar). Membuat objek Paint adalah operasi yang mahal, oleh karena itu harus dibuat sekali dan digunakan kembali.
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)
}
Dalam contoh ini digunakan dua Paint: satu untuk mengisi lingkaran dengan warna ungu, yang kedua untuk garis tepi putih. Pemisahan menjadi fill dan stroke adalah praktik standar yang memungkinkan pengelolaan tampilan secara fleksibel tanpa membuat ulang objek.
Untuk isian gradien, Paint menerima Shader — subkelas LinearGradient, RadialGradient, SweepGradient. Shader dilampirkan ke Paint melalui metode setShader() dan menentukan bagaimana warna berubah di area gambar.
Canvas mendukung transformasi matriks sistem koordinat: translate() (pergeseran), rotate() (rotasi), scale() (skala) dan skew() (miring). Transformasi menumpuk: setiap panggilan berikutnya diterapkan di atas yang sebelumnya.
Manajemen tumpukan transformasi dilakukan melalui save() dan restore(). save() menyimpan status Canvas saat ini (matriks, clip) ke tumpukan, restore() mengembalikan status terakhir yang disimpan. Di antara save() dan restore() dapat ada transformasi bersarang.
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
canvas.save() // Simpan status awal
canvas.translate(100f, 100f) // Pindahkan titik asal
// Kotak pertama
canvas.drawRect(0f, 0f, 50f, 50f, fillPaint)
canvas.save() // Simpan setelah pergeseran
canvas.rotate(45f, 25f, 25f) // Putar di sekitar pusat kotak
// Kotak diputar
canvas.drawRect(0f, 0f, 50f, 50f, strokePaint)
canvas.restore() // Pulihkan setelah putaran
canvas.restore() // Pulihkan status awal
}
Selalu gunakan save() sebelum memulai transformasi dan restore() setelah selesai. Save/restore yang tidak seimbang menyebabkan akumulasi matriks dan penggambaran elemen berikutnya yang tidak benar.
Untuk grafis kompleks, Canvas dikombinasikan dengan Bitmap dan Path. Bitmap digunakan untuk memuat gambar dan caching frame yang telah di-render. Path — untuk membangun kurva Bezier arbitrer, poligon, dan kontur kompleks.
Teknik rendering offscreen: Bitmap dibuat, di atasnya digambar scene kompleks melalui Canvas terpisah, dan kemudian Bitmap yang siap ditampilkan di onDraw() melalui drawBitmap(). Ini memungkinkan memperbarui grafis kompleks tanpa menggambar ulang setiap frame sepenuhnya.
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)
// Render scene sekali
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 digunakan untuk membangun kontur kompleks: kurva Bezier (quadTo, cubicTo), busur (arcTo), garis (lineTo). Path dapat tertutup (close()) untuk bentuk yang diisi atau terbuka untuk garis. Metode utama drawPath() menggabungkan Path dan Paint untuk penggambaran akhir.
Kinerja penggambaran Canvas secara langsung mempengaruhi FPS aplikasi. Masalah utama: alokasi berlebihan di onDraw(), invalidate() yang sering dan penggunaan Percepatan Hardware yang tidak optimal.
Paint, Path, Rect, RectF dan objek lainnya harus dibuat sekali di inisialisator atau metode setup(). Setiap alokasi di onDraw() membebani garbage collector, yang menyebabkan mikro-lag. Pengecualian — static atau companion object untuk objek immutable.
Jika sebagian besar View tersembunyi di luar area yang terlihat (misalnya di ScrollView), gunakan canvas.clipRect() untuk membatasi penggambaran. Percepatan Hardware dalam hal ini mengoptimalkan pemotongan piksel yang tidak terlihat.
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
// Klip ke area terlihat
canvas.save()
canvas.clipRect(scrollX, scrollY, scrollX + width, scrollY + height)
// Render scene besar
renderScene(canvas)
canvas.restore()
}
Gunakan View.setLayerType() dengan LAYER_TYPE_HARDWARE untuk View dengan grafis Canvas kompleks yang jarang diperbarui. Untuk animasi yang sering diperbarui, gunakan LAYER_TYPE_NONE untuk menghindari pembaruan layer hardware yang mahal. Profil melalui GPU Profile Rendering dan Android Studio Profiler.
Pertanyaan yang Sering Diajukan
Ya, bisa membuat Canvas(Bitmap) — konstruktor yang menerima Bitmap. Ini digunakan untuk rendering offscreen: Anda menggambar di Bitmap, kemudian menampilkannya melalui drawBitmap(). Canvas juga dapat dibuat dari Surface (untuk SurfaceView) atau melalui Picture.
Canvas — adalah API untuk menggambar di View di thread UI. SurfaceView — adalah Surface terpisah yang dapat diperbarui dari thread latar belakang melalui Canvas sendiri (lockCanvas() / unlockCanvasAndPost()). SurfaceView lebih disukai untuk game dan video.
Penyebab paling umum adalah save() dan restore() yang tidak seimbang. Jika setelah transformasi (translate, rotate) tidak dipanggil restore(), Canvas tetap dalam sistem koordinat yang berubah, dan elemen berikutnya digambar dengan pergeseran. Periksa pasangan save()/restore().
Gunakan Paint.setTextAlign(Paint.Align.CENTER) untuk perataan horizontal dan Paint.getTextBounds() atau Paint.descent() / ascent() untuk vertikal. Penengahan: canvas.drawText(text, centerX, centerY - (ascent + descent) / 2, paint).
Canvas sendiri tidak menganimasikan — ia hanya menggambar status saat ini. Animasi dicapai melalui panggilan berurutan invalidate() (atau postInvalidateOnAnimation()), setiap kali menggambar frame baru di onDraw(). Untuk animasi halus gunakan ValueAnimator atau Choreographer untuk sinkronisasi dengan Vsync.
Kesimpulan
Kami akan mengembangkan aplikasi seluler turnkey
IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.
Baca juga