Android-da Canvas — android.graphics paketidagi View-da 2D chizish uchun API ta'minlovchi sinf. Canvas xuddi tuval kabi ishlaydi, unda dasturchi turli draw* metodlari yordamida geometrik shakllar, matn, tasvirlar va yo'llarni chizadi. Android Developers Documentation (2025) ma'lumotiga ko'ra, Canvas Android-da maxsus chizish uchun asosiy vositadir va uslublar va ranglarni belgilash uchun Paint sinfi bilan birga ishlatiladi. Har bir onDraw() chaqiruvi view-ning bitmap bufferi bilan bog'langan tayyor Canvas namunasini oladi.
Asosiy ma'lumotlar
Canvas — Android-da markaziy 2D grafik sinfi bo'lib, tekislikda chizish uchun metodlarni ta'minlaydi. Har bir Canvas Bitmap bilan bog'langan — chizish operatsiyalari natijalari yoziladigan xotira maydoni. View qayta chizilganda, tizim onDraw()-ga ushbu View-ning bufferi bilan bog'langan Canvas-ni uzatadi.
Canvas koordinatalar tizimida ishlaydi, bunda (0,0) yuqori chap burchak, X o'qi o'ngga, Y o'qi pastga ketadi. Barcha chizish operatsiyalari Canvas-ning joriy holatidan, jumladan transformatsiya matritsasi, kesish maydoni (clip) va Paint uslubidan foydalanadi. Android Documentation (2025) ma'lumotiga ko'ra, Canvas API turli grafik primitivlar uchun 30 dan ortiq draw* metodini o'z ichiga oladi.
Android 3.0 (API 11) dan boshlab Canvas DisplayList orqali apparat tezlashtirishni qo'llab-quvvatlaydi. Tezlashtirilgan rejimda Canvas operatsiyalari DisplayList-ga yoziladi va keyin GPU-da bajariladi. Bu ishlashni sezilarli darajada oshiradi, lekin cheklovlar qo'yadi: ba'zi Canvas operatsiyalari (Path bo'lmagan klip bilan clipPath) tezlashtirilgan rejimda qo'llab-quvvatlanmaydi.
Canvas asosiy primitivlarni chizish uchun metodlar to'plamini ta'minlaydi. Har bir metod geometrik parametrlar va vizual uslubni belgilaydigan Paint obyektini qabul qiladi.
| Metod | Maqsad | Misol |
|---|---|---|
| drawRect() | To'rtburchak chizish | canvas.drawRect(10f, 10f, 100f, 100f, paint) |
| drawCircle() | Doira chizish | canvas.drawCircle(50f, 50f, 30f, paint) |
| drawLine() | Chiziq chizish | canvas.drawLine(0f, 0f, 100f, 100f, paint) |
| drawText() | Matn chizish | canvas.drawText("Hello", 10f, 20f, paint) |
| drawBitmap() | Tasvir chizish | canvas.drawBitmap(bitmap, 0f, 0f, paint) |
| drawPath() | Ixtiyoriy yo'l chizish | canvas.drawPath(path, paint) |
| drawOval() | Oval chizish | canvas.drawOval(rectF, paint) |
| drawArc() | Yoy yoki sektor chizish | canvas.drawArc(rectF, 0f, 90f, true, paint) |
Har bir metod istalgan tartibda chaqirilishi mumkin — Canvas chaqiruvlar tartibida chizadi, yangi elementlarni oldingilari ustiga qo'yadi. Murakkab kompozitsiyalar uchun Canvas holatini saqlash va tiklash bilan ko'p qatlamli chizish texnikasi qo'llaniladi.
Paint — Canvas qanday chizishini belgilaydigan sinf. Paint bo'lmasa, Canvas metodlari foydasiz — u rang, chiziq qalinligi, to'ldirish uslubi, matn o'lchami, effektlar (soya, gradient, xiralash) va aralashtirish rejimini belgilaydi.
Paint-ning asosiy xususiyatlari: color (rang), style (FILL, STROKE yoki FILL_AND_STROKE), strokeWidth (chiziq qalinligi), textSize (matn o'lchami), isAntiAlias (tekislash), shader (gradient yoki tasvir). Paint obyektini yaratish qimmat operatsiya, shuning uchun uni bir marta yaratib, qayta ishlatish kerak.
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)
}
Ushbu misolda ikkita Paint ishlatiladi: biri doirani binafsha rang bilan to'ldirish uchun, ikkinchisi oq kontur uchun. Fill va stroke ga bo'lish — obyektlarni qayta yaratmasdan tashqi ko'rinishni moslashuvchan boshqarish imkonini beradigan standart amaliyotdir.
Gradient to'ldirishlar uchun Paint Shader qabul qiladi — LinearGradient, RadialGradient, SweepGradient pastki sinflari. Shader setShader() metodi orqali Paint-ga biriktiriladi va rangning chizish maydonida qanday o'zgarishini belgilaydi.
Canvas koordinatalar tizimining matritsali o'zgartirishlarini qo'llab-quvvatlaydi: translate() (siljitish), rotate() (aylantirish), scale() (masshtablash) va skew() (qiyshatish). Transformatsiyalar yig'iladi: har bir keyingi chaqiruv avvalgilariga qo'llaniladi.
Transformatsiyalar stekini boshqarish save() va restore() orqali amalga oshiriladi. save() Canvas-ning joriy holatini (matritsa, clip) stekda saqlaydi, restore() oxirgi saqlangan holatni tiklaydi. save() va restore() o'rtasida ichma-ich transformatsiyalar bo'lishi mumkin.
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
canvas.save() // Boshlang'ich holatni saqlash
canvas.translate(100f, 100f) // Koordinata boshini siljitish
// Birinchi kvadrat
canvas.drawRect(0f, 0f, 50f, 50f, fillPaint)
canvas.save() // Siljitishdan keyin saqlash
canvas.rotate(45f, 25f, 25f) // Kvadrat markazi atrofida aylantirish
// Aylantirilgan kvadrat
canvas.drawRect(0f, 0f, 50f, 50f, strokePaint)
canvas.restore() // Aylantirishdan keyin tiklash
canvas.restore() // Boshlang'ich holatni tiklash
}
Har doim transformatsiyalarni boshlashdan oldin save() dan foydalaning va tugatgandan keyin restore() ni chaqiring. Muvozanatsiz save/restore matritsaning yig'ilishiga va keyingi elementlarning noto'g'ri chizilishiga olib keladi.
Murakkab grafikalar uchun Canvas Bitmap va Path bilan birlashtiriladi. Bitmap tasvirlarni yuklash va renderlangan kadrlarni keshlash uchun ishlatiladi. Path — ixtiyoriy Bezier egri chiziqlari, ko'pburchaklar va murakkab konturlar qurish uchun.
Offscreen-rendering texnikasi: Bitmap yaratiladi, unda alohida Canvas orqali murakkab sahna chiziladi va tayyor Bitmap onDraw()-da drawBitmap() orqali ko'rsatiladi. Bu har bir kadrda to'liq qayta chizmasdan murakkab grafikani yangilash imkonini beradi.
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)
// Sahnani bir marta renderlash
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 murakkab konturlar qurish uchun ishlatiladi: Bezier egri chiziqlari (quadTo, cubicTo), yoylar (arcTo), chiziqlar (lineTo). Path to'ldirilgan shakllar uchun yopiq (close()) yoki chiziqlar uchun ochiq bo'lishi mumkin. drawPath() asosiy metodlari yakuniy chizish uchun Path va Paint-ni birlashtiradi.
Canvas chizish samaradorligi to'g'ridan-to'g'ri ilovaning FPS-iga ta'sir qiladi. Asosiy muammolar: onDraw()-da ortiqcha alokatsiyalar, tez-tez invalidate() va apparat tezlashtirishdan optimal foydalanmaslik.
Paint, Path, Rect, RectF va boshqa obyektlar bir marta inizializatorda yoki setup() metodida yaratilishi kerak. onDraw()-dagi har bir alokatsiya garbage collector-ni yuklaydi, bu esa mikro-laglarga olib keladi. Istisno — immutable obyektlar uchun static yoki companion object.
Agar View-ning katta qismi ko'rinadigan maydondan tashqarida yashirin bo'lsa (masalan, ScrollView-da), chizishni cheklash uchun canvas.clipRect() dan foydalaning. Apparat tezlashtirish bu holda ko'rinmaydigan piksellarni kesishni qo'shimcha optimallashtiradi.
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
// Ko'rinadigan maydonga kesish
canvas.save()
canvas.clipRect(scrollX, scrollY, scrollX + width, scrollY + height)
// Katta sahnani renderlash
renderScene(canvas)
canvas.restore()
}
Kamdan-kam yangilanadigan murakkab Canvas grafikasi bo'lgan View uchun View.setLayerType() ni LAYER_TYPE_HARDWARE bilan ishlating. Tez-tez yangilanadigan animatsiyalar uchun LAYER_TYPE_NONE dan foydalaning, apparat qatlamining qimmat yangilanishidan qochish uchun. GPU Profile Rendering va Android Studio Profiler orqali profiling qiling.
Ko'p beriladigan savollar
Ha, Canvas(Bitmap) — Bitmap qabul qiluvchi konstruktor yaratish mumkin. Bu offscreen-rendering uchun ishlatiladi: Bitmap ustida chizasiz, keyin uni drawBitmap() orqali ko'rsatasiz. Canvas shuningdek Surface-dan (SurfaceView uchun) yoki Picture orqali yaratilishi mumkin.
Canvas — UI thread-da View-da chizish uchun API. SurfaceView — o'z Canvas-i (lockCanvas() / unlockCanvasAndPost()) orqali fon thread-dan yangilanishi mumkin bo'lgan alohida Surface. SurfaceView o'yinlar va video uchun afzal.
Eng keng tarqalgan sabab — muvozanatsiz save() va restore(). Agar transformatsiyadan (translate, rotate) keyin restore() chaqirilmasa, Canvas o'zgartirilgan koordinatalar tizimida qoladi va keyingi elementlar siljish bilan chiziladi. save()/restore() juftliklarini tekshiring.
Gorizontal markazlashtirish uchun Paint.setTextAlign(Paint.Align.CENTER) va vertikal uchun Paint.getTextBounds() yoki Paint.descent() / ascent() dan foydalaning. Markazlashtirish: canvas.drawText(text, centerX, centerY - (ascent + descent) / 2, paint).
Canvas o'zi animatsiya qilmaydi — u faqat joriy holatni chizadi. Animatsiya ketma-ket invalidate() (yoki postInvalidateOnAnimation()) chaqiruvlari orqali erishiladi, har safar onDraw()-da yangi kadr chiziladi. Silliq animatsiyalar uchun Vsync bilan sinxronizatsiya uchun ValueAnimator yoki Choreographer dan foydalaning.
Xulosa
Biz kalit topshirig'i bilan mobil ilovani ishlab chiqamiz
IT Sectr 2017-yildan beri startaplar va korxonalar uchun iOS va Android ilovalarini yaratadi. Biz sizga maslahat beramiz va eng yaxshi yechimni taklif qilamiz.