View personalizzate
Disegni componenti dell'interfaccia personalizzati da zero. Estenda View, implementi onMeasure e onDraw con Canvas e Paint, definisca attributi XML personalizzati e costruisca view composite.
View personalizzate è una lezione Android Academy gratuita su CoddyKit. Questa è la lezione 3 di 5. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Android Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Android Academy include 5 lezioni in totale.
Perché utilizzare view personalizzate?
A volte le view Android integrate non fanno esattamente ciò che serve. Le view personalizzate consentono di:
- D disegnare forme, grafici, anelli di avanzamento o diagrammi che non esistono nell'SDK
- Creare componenti UI con il brand, utilizzati in modo coerente in tutta l'app
- Combinare più view in un unico componente riutilizzabile (Compound View)
- Ottenere prestazioni migliori eliminando gerarchie di layout annidate
Estensione di View
Crei una view personalizzata estendendo View o una sottoclasse come ImageView. Esegua l'override del costruttore richiesto:
class CircleProgressView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {
var progress: Float = 0f
set(value) {
field = value.coerceIn(0f, 100f)
invalidate() // trigger redraw
}
// onMeasure and onDraw go here
}onMeasure()
onMeasure() comunica al genitore quanto vorrebbe essere grande questa view. Chiami sempre setMeasuredDimension() alla fine:
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
val desiredSize = 200 // dp → pixels
val px = (desiredSize * resources.displayMetrics.density).toInt()
val width = resolveSize(px, widthMeasureSpec)
val height = resolveSize(px, heightMeasureSpec)
// Square: same width and height
val size = minOf(width, height)
setMeasuredDimension(size, size)
}Paint — lo strumento di disegno
Un oggetto Paint contiene le informazioni di stile per il disegno, come colore, spessore del tratto e anti-aliasing. Lo crei una sola volta, mai all'interno di onDraw():
class CircleProgressView ... : View(...) {
// Create Paint in init, not in onDraw!
private val backgroundPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
color = Color.LTGRAY
style = Paint.Style.STROKE
strokeWidth = 20f
strokeCap = Paint.Cap.ROUND
}
private val progressPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
color = Color.parseColor("#6750A4")
style = Paint.Style.STROKE
strokeWidth = 20f
strokeCap = Paint.Cap.ROUND
}
}onDraw() — disegno della view
onDraw(canvas) viene chiamato ogni volta che la view deve essere ridisegnata. Utilizzi Canvas per disegnare forme, testo e bitmap:
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
val cx = width / 2f
val cy = height / 2f
val radius = (minOf(width, height) / 2f) - 30f
// Draw background circle
canvas.drawCircle(cx, cy, radius, backgroundPaint)
// Draw progress arc
val oval = RectF(cx - radius, cy - radius, cx + radius, cy + radius)
val sweepAngle = 360f * (progress / 100f)
canvas.drawArc(oval, -90f, sweepAngle, false, progressPaint)
}invalidate() e requestLayout()
Due metodi per attivare un aggiornamento:
invalidate()— ridisegna la view, chiamandoonDraw. Lo utilizzi quando cambia il contenuto ma le dimensioni restano uguali.requestLayout()— ricalcola le misure e ridisegna, chiamando primaonMeasuree poionDraw. Lo utilizzi quando cambiano le dimensioni della view.
Attributi personalizzati (attrs.xml)
Dichiari attributi XML personalizzati per configurare la view dai file di layout:
<!-- res/values/attrs.xml -->
<resources>
<declare-styleable name="CircleProgressView">
<attr name="progressColor" format="color" />
<attr name="trackColor" format="color" />
<attr name="strokeWidth" format="dimension" />
<attr name="progress" format="float" />
</declare-styleable>
</resources>Lettura degli attributi personalizzati
Legga gli attributi nel costruttore utilizzando obtainStyledAttributes:
init {
context.obtainStyledAttributes(attrs, R.styleable.CircleProgressView).use { ta ->
progressPaint.color = ta.getColor(
R.styleable.CircleProgressView_progressColor,
Color.parseColor("#6750A4")
)
backgroundPaint.color = ta.getColor(
R.styleable.CircleProgressView_trackColor,
Color.LTGRAY
)
val sw = ta.getDimension(R.styleable.CircleProgressView_strokeWidth, 20f)
progressPaint.strokeWidth = sw
backgroundPaint.strokeWidth = sw
progress = ta.getFloat(R.styleable.CircleProgressView_progress, 0f)
}
}Utilizzo della view personalizzata in XML
Utilizzi la view personalizzata nel layout XML con il percorso completo della classe e gli attributi personalizzati:
<!-- In any layout XML -->
<com.example.myapp.CircleProgressView
android:id="@+id/progressView"
android:layout_width="120dp"
android:layout_height="120dp"
app:progress="65"
app:progressColor="@color/primary"
app:trackColor="@color/surface_variant"
app:strokeWidth="12dp" />
<!-- Control in code: -->
binding.progressView.progress = 75fCompound View
Una compound view combina view esistenti in un unico componente riutilizzabile. Estenda una classe di layout come LinearLayout:
class SearchBarView @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null
) : LinearLayout(context, attrs) {
private val binding = ViewSearchBarBinding.inflate(LayoutInflater.from(context), this)
init {
orientation = HORIZONTAL
binding.ivSearch.setOnClickListener {
onSearchClick?.invoke(binding.etSearch.text.toString())
}
}
var onSearchClick: ((String) -> Unit)? = null
fun setHint(hint: String) { binding.etSearch.hint = hint }
}Disegno del testo
Disegni il testo su un Canvas con drawText(). Lo centri con precisione utilizzando Paint.getFontMetrics():
private val textPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
color = Color.BLACK
textSize = 48f
textAlign = Paint.Align.CENTER
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
val cx = width / 2f
val cy = height / 2f
// Vertically center the text:
val fm = textPaint.fontMetrics
val textY = cy - (fm.ascent + fm.descent) / 2f
canvas.drawText("${progress.toInt()}%", cx, textY, textPaint)
}Verifica rapida
Quale metodo dovrebbe chiamare per ridisegnare la view personalizzata quando cambiano i dati ma le dimensioni restano uguali?
Riepilogo: view personalizzate
Ora può disegnare qualsiasi cosa sullo schermo:
- Estenda
Viewcon@JvmOverloads constructor onMeasure()— comunichi le dimensioni desiderate consetMeasuredDimension()Paint— definisca lo stile; lo crei una sola volta, non all'interno dionDraw()onDraw(canvas)— disegni cerchi, archi, testo e bitmap- Utilizzi
invalidate()per ridisegnare erequestLayout()per ricalcolare le misure - Attributi personalizzati tramite
attrs.xmlper la configurazione XML - Compound view — estenda un layout per combinare view esistenti
Prossimo argomento: dia vita alla UI con animazioni e transizioni.
Domande Frequenti
La lezione «View personalizzate» è gratuita?
Sì — il testo completo di «View personalizzate» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Android Academy, passa a CoddyKit PRO. Il corso Android Academy include 5 lezioni in totale.
Cosa imparerò in «View personalizzate»?
Disegni componenti dell'interfaccia personalizzati da zero. Estenda View, implementi onMeasure e onDraw con Canvas e Paint, definisca attributi XML personalizzati e costruisca view composite. Eserciti Android Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.
Ho bisogno di esperienza per iniziare Android Academy?
Non è richiesta alcuna esperienza precedente. Android Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 3 di 5.
Quanto tempo richiede la lezione «View personalizzate»?
La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.
Posso scrivere ed eseguire codice in questa lezione Android Academy?
Sì. Ogni lezione Android Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.
Tutte le lezioni di questo corso
- Nozioni di base di Material Design
- Temi e stili
- View personalizzate
- Animazioni e transizioni
- Navigazione inferiore e schede