Benutzerdefinierte Views
Zeichnen Sie benutzerdefinierte UI-Komponenten von Grund auf. Erweitern Sie View, implementieren Sie onMeasure und onDraw mit Canvas und Paint, definieren Sie benutzerdefinierte XML-Attribute und erstellen Sie zusammengesetzte Views.
Benutzerdefinierte Views ist eine kostenlose Android Academy-Lektion auf CoddyKit. Dies ist Lektion 3 von 5. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des Android Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der Android Academy-Kurs umfasst insgesamt 5 Lektionen.
Warum benutzerdefinierte Views?
Manchmal bieten die integrierten Android-Views nicht genau die benötigten Funktionen. Mit benutzerdefinierten Views können Sie:
- Formen, Diagramme, Fortschrittsringe oder andere im SDK nicht vorhandene Elemente zeichnen
- Markenspezifische UI-Komponenten erstellen, die in der gesamten App konsistent verwendet werden
- Mehrere Views zu einer wiederverwendbaren Komponente kombinieren (Compound View)
- Durch das Vermeiden verschachtelter Layout-Hierarchien eine bessere Performance erzielen
View erweitern
Erstellen Sie eine benutzerdefinierte View, indem Sie View (oder eine Unterklasse wie ImageView) erweitern. Überschreiben Sie den erforderlichen Konstruktor:
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() teilt dem übergeordneten Element mit, wie groß diese View sein möchte. Rufen Sie am Ende immer setMeasuredDimension() auf:
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 — das Zeichenwerkzeug
Ein Paint-Objekt enthält die Stilinformationen zum Zeichnen (Farbe, Strichbreite, Anti-Aliasing). Erstellen Sie es einmal — niemals innerhalb von 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() — die View zeichnen
onDraw(canvas) wird jedes Mal aufgerufen, wenn die View neu gezeichnet werden muss. Verwenden Sie den Canvas, um Formen, Text und Bitmaps zu zeichnen:
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() und requestLayout() im Vergleich
Zwei Methoden, um eine Aktualisierung auszulösen:
invalidate()— zeichnet die View neu (ruftonDrawauf). Verwenden Sie die Methode, wenn sich der Inhalt ändert, die Größe aber gleich bleibt.requestLayout()— misst die View neu und zeichnet sie erneut (ruft zuerstonMeasureund dannonDrawauf). Verwenden Sie die Methode, wenn sich die Größe der View ändert.
Benutzerdefinierte Attribute (attrs.xml)
Definieren Sie benutzerdefinierte XML-Attribute, damit die View über Layout-Dateien konfiguriert werden kann:
<!-- 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>Benutzerdefinierte Attribute auslesen
Lesen Sie attrs im Konstruktor mit obtainStyledAttributes aus:
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)
}
}Benutzerdefinierte View in XML verwenden
Verwenden Sie Ihre benutzerdefinierte View im Layout-XML mit dem vollständigen Klassenpfad und den benutzerdefinierten Attributen:
<!-- 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 Views
Eine Compound View kombiniert vorhandene Views zu einer wiederverwendbaren Komponente. Erweitern Sie eine Layout-Klasse wie 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 }
}Text zeichnen
Zeichnen Sie Text mit drawText() auf einem Canvas. Zentrieren Sie ihn mithilfe von Paint.getFontMetrics() präzise:
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)
}Kurze Überprüfung
Welche Methode sollten Sie aufrufen, um Ihre benutzerdefinierte View neu zu zeichnen, wenn sich die Daten ändern, die Größe aber gleich bleibt?
Zusammenfassung: Benutzerdefinierte Views
Sie können jetzt beliebige Elemente auf dem Bildschirm zeichnen:
Viewmit@JvmOverloads constructorerweiternonMeasure()— die gewünschte Größe mitsetMeasuredDimension()meldenPaint— den Stil festlegen; einmal erstellen, nicht innerhalb vononDraw()onDraw(canvas)— Kreise, Bögen, Text und Bitmaps zeichneninvalidate()zum Neuzeichnen,requestLayout()zum erneuten Messen- Benutzerdefinierte Attribute über
attrs.xmlzur Konfiguration per XML - Compound View — ein Layout erweitern, um vorhandene Views zu kombinieren
Als Nächstes: Erwecken Sie Ihre UI mit Animationen und Übergängen zum Leben.
Häufig gestellte Fragen
Ist die Lektion „Benutzerdefinierte Views“ kostenlos?
Ja — der vollständige Text von „Benutzerdefinierte Views“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des Android Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der Android Academy-Kurs umfasst insgesamt 5 Lektionen.
Was lerne ich in „Benutzerdefinierte Views“?
Zeichnen Sie benutzerdefinierte UI-Komponenten von Grund auf. Erweitern Sie View, implementieren Sie onMeasure und onDraw mit Canvas und Paint, definieren Sie benutzerdefinierte XML-Attribute und ers… Du übst Android Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.
Brauche ich Erfahrung, um Android Academy zu starten?
Keine Vorkenntnisse erforderlich. Android Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 3 von 5.
Wie lange dauert die Lektion „Benutzerdefinierte Views“?
Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.
Kann ich in dieser Android Academy-Lektion Code schreiben und ausführen?
Ja. Jede Android Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.
Alle Lektionen in diesem Kurs
- Grundlagen von Material Design
- Themes und Styles
- Benutzerdefinierte Views
- Animationen und Übergänge
- Untere Navigation und Tabs