Paint — clasa principală pentru stilizarea graficii în Android Canvas. Aceasta determină culoarea, grosimea liniei, stilul de umplere, efectele de estompare și fonturile pentru toate operațiile de desenare în interfața utilizatorului. Fără Paint, Canvas nu poate aplica atribute vizuale elementelor afișate. Conform Google Developers, 2026, Paint suportă până la 42 de parametri de stil, inclusiv gradiente și texturi.
Principalele puncte
Paint — o clasă din pachetul android.graphics care stochează toate setările de stil pentru operațiile de desenare pe Canvas. Nu conține pixelii în sine, ci determină cum vor arăta liniile, formele și textul. Fiecare apel de metodă Canvas — drawCircle, drawLine, drawText — folosește Paint pentru interpretarea reprezentării vizuale.
Paint funcționează pe principiul unui obiect de configurare. Creezi o instanță, setezi parametrii o dată și o reutilizezi pentru multiple operații. Acest lucru minimizează numărul de alocări în bucla de desenare și crește performanța cu până la 30% față de crearea unui obiect nou în fiecare cadru. Conform Google I/O 2024, optimizarea Paint este una dintre practicile cheie pentru atingerea a 60 FPS în grafica personalizată.
Toate setările Paint sunt împărțite în mai multe categorii: culoare și transparență, stilul conturului și umplerii, lucrul cu textul și fonturile, efecte de estompare și mascare. Fiecare categorie este gestionată prin metode setter separate, care pot fi combinate în orice combinație. Acest lucru face API-ul Paint flexibil, dar necesită înțelegerea interacțiunii parametrilor — de exemplu, Style influențează dacă Shader se aplică conturului sau umplerii.
setColor — metoda principală de setare a culorii pentru toate operațiile ulterioare de desenare. Culoarea este transmisă în format ARGB (număr întreg pe 32 de biți), unde primii 8 biți reprezintă canalul alfa, iar restul — canalele roșu, verde și albastru. Valoarea 0xFF0000FF setează culoarea albastru opac.
Metoda setAlpha permite reglarea independentă a transparenței în intervalul de la 0 (complet transparent) la 255 (complet opac). Spre deosebire de specificarea alfa în setColor, această metodă nu afectează nuanța de culoare deja setată — modulează doar transparența generală. Acest lucru este convenabil pentru animațiile de apariție și dispariție a elementelor fără schimbarea culorii.
ColorFilter — mecanism de transformare a culorii fiecărui pixel înainte de desenare. Sunt suportate trei moduri: LightingColorFilter pentru înmulțirea și adunarea canalelor, PorterDuffColorFilter pentru suprapunere cu moduri de amestecare și ColorMatrixColorFilter pentru transformare matriceală completă. ColorFilter se aplică după Shader, dar înainte de ieșirea pe Canvas.
Pentru majoritatea sarcinilor, setColor sau setAlpha standard sunt suficiente. ColorFilter este folosit în principal pentru efecte de decolorare, sepia sau inversare. Utilizarea ColorFilter crește încărcarea GPU, de aceea Google recomandă minimizarea utilizării sale în apelurile ciclice onDraw.
| Metodă | Descriere | Performanță |
|---|---|---|
| setColor | Setează culoarea în ARGB | O(1) — fără costuri suplimentare |
| setAlpha | Reglează transparența (0-255) | O(1) — operație ușoară |
| setColorFilter | Aplică corecția culorii | O(n) — afectează FPS la apeluri frecvente |
Metoda setStyle acceptă una dintre cele trei valori Paint.Style: FILL (umplere), STROKE (contur) sau FILL_AND_STROKE (simultan). De alegerea stilului depinde dacă figura va fi afișată ca siluetă, ca schelet sau ca contur cu umplere interioară. În mod implicit, Paint este creat cu stilul FILL.
setStrokeWidth setează grosimea liniei în pixeli pentru modul STROKE. Pentru forme rotunjite și colțuri rotunjite se folosesc setStrokeCap (Cap.ROUND, BUTT, SQUARE) și setStrokeJoin (Join.MITER, ROUND, BEVEL). Acești parametri influențează critic aspectul graficelor, căilor și ramelor în View-uri personalizate.
La o grosime mai mică de 1 pixel, linia este desenată cu precizie subpixel, dar poate părea neclară pe ecranele cu densitate scăzută. Pentru ecranele Retina Android folosiți TypedValue.applyDimension pentru conversia dp în pixeli. O grosime de 2 dp asigură vizibilitate clară pe majoritatea dispozitivelor.
DashPathEffect creează linii punctate și întrerupte. Constructorul acceptă un tablou de lungimi alternative de linii și spații și o deplasare inițială de fază. De exemplu, tabloul [10, 5, 3, 5] creează o linie cu o linie lungă, un spațiu scurt, o linie scurtă și un spațiu. Acest efect este folosit activ în editorii grafici și instrumentele de adnotare.
Combinarea stilurilor se realizează prin setPathEffect. Combinând CornerPathEffect, DashPathEffect și DiscretePathEffect, se pot crea linii vizuale complexe pentru diagrame, legende și elemente decorative. Fiecare PathEffect este calculat pe CPU, de aceea în animațiile cu un număr mare de linii se recomandă rasterizarea prealabilă a efectului în 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 — obiectul care determină garnitura de font pentru toate operațiile text ale Paint. Android suportă fonturi sistemice (Roboto, Noto Sans), fonturi personalizate din resursele assets și fonturi încărcabile prin Downloadable Fonts API. Setarea Typeface se face prin setTypeface pe instanța Paint.
Metoda setTextSize setează dimensiunea fontului în pixeli. Pentru afișarea corectă pe diferite ecrane, se recomandă specificarea dimensiunii în sp cu ajutorul TypedValue.applyDimension. Spațiul dintre rânduri se reglează prin setTextScaleX pentru întinderea orizontală și este inclus în suportul integrat pentru text MultiLine prin Canvas.drawText.
Pentru alinierea textului se folosește setTextAlign cu valorile LEFT, CENTER și RIGHT. La CENTER, coordonata x transmisă în drawText devine punctul central al textului — acest lucru este deosebit de convenabil pentru legendele de sub pictograme și titlurile din interiorul formelor. Pentru poziționarea precisă se aplică metodele measureText și getTextBounds, care returnează lățimea și dreptunghiul de delimitare al textului.
setUnderlineText și setStrikeThruText activează respectiv sublinierea și tăierea. Acești parametri funcționează la nivelul garniturii și se aplică întregului text desenat de Paint-ul respectiv. Pentru formatarea flexibilă a diferitelor părți ale aceluiași rând, utilizați obiecte Paint separate cu setări diferite sau comutați parametrii între apelurile drawText.
| Metodă | Scop | Unități de măsură |
|---|---|---|
| setTextSize | Dimensiunea fontului | px (pixeli) |
| setTextAlign | Aliniere orizontală | LEFT, CENTER, RIGHT |
| setTypeface | Garnitura fontului | Typeface object |
| setUnderlineText | Subliniere | Boolean |
Shader — clasa de bază pentru umplerea formelor cu gradiente, texturi bitmap și compozite. Prin metoda setShader se poate atribui oricare dintre subclase: LinearGradient, RadialGradient, SweepGradient, BitmapShader sau ComposeShader. Shader înlocuiește culoarea setată prin setColor și se aplică tuturor elementelor desenate.
LinearGradient creează o tranziție lină între două sau mai multe culori de-a lungul unei linii drepte. Constructorul acceptă punctele de început și sfârșit, un tablou de culori și pozițiile acestora (modul de placare). Modul de placare determină comportamentul în afara gradientului: CLAMP (repetarea ultimei culori), MIRROR (oglin dire) sau REPEAT (repetare). LinearGradient este utilizat activ pentru umpleri de fundal și bare de progres.
RadialGradient creează un gradient circular de la centru spre margini. Centrul este definit prin coordonate, raza determină zona de tranziție a culorilor. Aspectul gradientului radial amintește de iluminarea de la o sursă punctiformă — acesta este adesea folosit pentru simularea strălucirii butoanelor și iluminarea elementelor active.
BlurMaskFilter adaugă un efect de estompare în jurul elementelor desenate. Constructorul acceptă raza de estompare și stilul: NORMAL (estompare în toate direcțiile), INNER (doar în interiorul formei), OUTER (doar în exterior) și SOLID (forma + estompare exterioară). BlurMaskFilter funcționează cu orice tip de Paint și este adesea folosit pentru crearea umbrelor și efectelor de strălucire.
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))
}
Să analizăm un exemplu complet de View personalizat care desenează un cerc cu umplere gradient și o legendă text. Combinația Paint și Canvas permite crearea de grafică complexă cu un cod minim. Toate setările sunt mutate în inițializare pentru performanță.
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)
}
}
În cod sunt folosite două obiecte Paint separate: unul pentru umplerea cercului cu gradient radial, al doilea pentru text cu umbră prin BlurMaskFilter. O astfel de separare permite configurarea independentă a parametrilor și evitarea resetării stării Paint între desenarea diferitelor tipuri de elemente. Pentru creșterea performanței, ambele Paint sunt create în constructor, nu în onDraw.
La scalarea pe dispozitive cu densități diferite de pixeli, valorile dimensiunilor trebuie recalculate prin TypedValue.applyDimension. Fără aceasta, textul și gradientul vor arăta diferit pe ecranele mdpi și xxxhdpi. În exemplu, dimensiunea textului este setată în sp, care se adaptează automat la setările de sistem ale dimensiunii fontului utilizatorului.
Întrebări frecvente
Canvas execută operații de desenare (drawCircle, drawLine), iar Paint definește stilul — culoare, grosime, font. Canvas nu conține setări de stil, de aceea fără Paint nicio operație de desenare nu are efect vizual.
Da, un obiect Paint poate fi reutilizat pentru multiple forme. Se recomandă crearea de Paint-uri separate pentru diferite tipuri de elemente (fundal, text, contur), dar nu pentru fiecare formă — aceasta reduce încărcarea garbage collector-ului.
Metoda reset readuce Paint la o stare echivalentă cu o nouă instanță. Alternativ, se poate folosi set cu un flag, dar reset este preferabil pentru lizibilitatea codului. După resetare, toți parametrii de stil iau valorile implicite.
Crearea Paint în interiorul onDraw cauzează alocări în fiecare cadru, ceea ce duce la înghețuri GC. Toate obiectele Paint trebuie create în constructorul View. Modificarea parametrilor în onDraw prin setteri este sigură și nu creează obiecte noi.
Textul în Android se desenează întotdeauna cu fundal transparent. Metoda drawText afișează doar glifurile, fără dreptunghi de fundal. Dacă este nevoie de fundal sub text, desenați mai întâi un dreptunghi prin drawRoundRect cu un Paint separat, apoi textul.
Concluzii
Vom dezvolta o aplicație mobilă la cheie
IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.
Citiți și