Benutzerdefinierte Views sind die Grundlage einer einzigartigen Benutzeroberfläche jeder mobilen App. Benutzerdefinierte Views in mobilen Apps ermöglichen die Erstellung eigener Grafiken, Animationen und Elemente, die in Standardkomponenten nicht verfügbar sind. Laut Apple Developer, 2025 bleibt drawRect die primäre Methode für benutzerdefiniertes Zeichnen in der iOS-Entwicklung. Auf Android übernimmt onDraw mit Canvas dieselbe Rolle, und in Flutter — CustomPainter.
Das Wichtigste
Benutzerdefinierte Views sind benutzerdefinierte Oberflächenkomponenten, die Standardmethoden zum Zeichnen und Messen überschreiben, um einzigartige Grafiken zu erstellen. Diagramme, Animationen, Charts, benutzerdefinierte Chat-Elemente und AR-Masken — typische Anwendungsszenarien für benutzerdefinierte Views in mobilen Apps. Standard-UI-Komponenten (Button, TextView, Label) decken 80% der Aufgaben ab, aber die restlichen 20% erfordern vollständige Kontrolle über das Zeichnen in der mobilen Entwicklung. Das Zeichnen in der mobilen Entwicklung ist eine Fähigkeit, die einen Junior-Entwickler von einem Senior unterscheidet.
Benutzerdefinierte Views in mobilen Apps werden für einzigartige 2D-Grafiken, komplexe Animationen, Diagramme und Datenvisualisierung benötigt. Wenn das Standard-UIKit das erforderliche Element nicht bereitstellt — wird ein benutzerdefinierter View erstellt. In mobilen Apps werden benutzerdefinierte Views für Fortschrittsbalken, benutzerdefinierte Schaltflächen, Farbverläufe, animierte Symbole und Zeichenflächen für Finger verwendet. Es ist wichtig, nicht zu übertreiben — für einfache Stile reicht es, Standardkomponenten über die Appearance API zu konfigurieren.
Auf iOS werden benutzerdefinierte Views durch Ableiten von UIView und Überschreiben der drawRect-Methode erstellt. drawRect wird beim ersten Rendern und nach jedem setNeedsDisplay()-Aufruf aufgerufen. Innerhalb von drawRect erhält der Entwickler einen CGContext über UIGraphicsGetCurrentContext() — eine Leinwand für Linien, Formen, Farbverläufe und Text. Core Graphics (Quartz 2D) ist eine niedrigschwellige CPU-basierte Rendering-Engine, die volle Kontrolle über jedes Pixel bietet. UIBezierPath ist ein praktischer Wrapper zum Erstellen von Pfaden mit prägnanter Syntax.
class CircleView: UIView {
private var fillColor: UIColor = .systemBlue
override func drawRect(_ rect: CGRect) {
guard let ctx = UIGraphicsGetCurrentContext() else { return }
ctx.setFillColor(fillColor.cgColor)
ctx.addEllipse(in: bounds.insetBy(dx: 4, dy: 4))
ctx.drawPath(using: .fill)
}
func updateColor(_ newColor: UIColor) {
fillColor = newColor
setNeedsDisplay()
}
}
Core Graphics bietet CGContext — eine Leinwand für alle Zeichenoperationen. CGGradient erstellt lineare und radiale Farbverläufe mit Unterstützung für CGColorSpace (sRGB, Display P3). Transformationen werden über CGAffineTransform durchgeführt — eine 3x3-Matrix für Rotation, Skalierung und Verschiebung. CGContextTranslateCTM, CGContextRotateCTM und CGContextScaleCTM ändern das Koordinatensystem. Core Graphics läuft auf der CPU, daher können komplexe Grafiken den Prozessor belasten — verwenden Sie Metal für GPU-Beschleunigung.
UIBezierPath ist ein objektorientierter Wrapper über CGPath. Die Methode addArc(withCenter:radius:startAngle:endAngle:clockwise:) erstellt Bögen und Kreise, addCurve erstellt Bézier-Kurven. Pfade unterstützen Union-, Intersection- und Subtraktionsoperationen über addClip. UIBezierPath ist praktisch für benutzerdefinierte Masken (maskView), Beschneidungspfade und komplexe Formen — Sterne, Herzen, benutzerdefinierte Symbole.
Auf Android erweitert ein benutzerdefinierter View die View-Klasse mit überschriebenem onDraw(Canvas). Canvas enthält alle Zeichenmethoden in der mobilen Entwicklung: drawCircle, drawRect, drawLine, drawText, drawBitmap, drawPath und drawRoundRect. Paint konfiguriert Parameter — Farbe, Linienstärke, Stil (FILL, STROKE, FILL_AND_STROKE), Anti-Aliasing (isAntiAlias) und Textgröße. onDraw wird bei jedem invalidate() aufgerufen und sollte keine schweren Operationen enthalten — alle Berechnungen werden zwischengespeichert.
class CustomCircleView(context: Context, attrs: AttributeSet?)
: View(context, attrs) {
private val paint = Paint().apply {
style = Paint.Style.FILL
color = Color.BLUE
isAntiAlias = true
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
val cx = width / 2f
val cy = height / 2f
val radius = minOf(cx, cy) - 4f
canvas.drawCircle(cx, cy, radius, paint)
}
}
Path auf Android ist das Äquivalent zu UIBezierPath: addCircle, addRect, addOval, lineTo, cubicTo und quadTo. PathMeasure berechnet die Pfadlänge und Koordinaten an beliebigen Punkten — nützlich für die Animation der Bewegung eines Objekts entlang eines Pfads. Für Animationen wird ValueAnimator mit invalidate() im Callback verwendet. Der Animator kann Farbe, Radius, Position ändern — jede Eigenschaft, die das Zeichnen beeinflusst. Benutzerdefinierte Views auf Android unterstützen auch StateListDrawable und animated-vector für Animationen über XML.
Farbverläufe auf Android werden über Shader festgelegt — LinearGradient, RadialGradient und SweepGradient. Shader wird Paint über paint.setShader(shader) zugewiesen. LinearGradient erzeugt einen linearen Farbverlauf zwischen zwei Punkten mit optionalen Farbpositionen. RadialGradient — radial von der Mitte zu den Rändern. SweepGradient — konisch um einen Mittelpunkt. Shader.TileMode (CLAMP, REPEAT, MIRROR) definiert das Verhalten außerhalb des Bereichs.
Flutter verwendet CustomPainter — eine Klasse mit den Methoden paint(Canvas canvas, Size size) und shouldRepaint. Canvas in Flutter bietet dieselben Methoden wie in Android: drawCircle, drawRect, drawLine, drawPath, drawParagraph und drawImage. Paint in Flutter konfiguriert Farbe, Stärke, Stil und Anti-Aliasing. Flutter verwendet weder drawRect noch onDraw — alles Zeichnen erfolgt über CustomPainter, eingebettet in das CustomPaint-Widget.
class CirclePainter extends CustomPainter {
final Color color;
CirclePainter({required this.color});
@override
void paint(Canvas canvas, Size size) {
final paint = Paint()
..color = color
..style = PaintingStyle.fill
..isAntiAlias = true;
final radius = size.shortestSide / 2 - 4;
canvas.drawCircle(size.center(Offset.zero), radius, paint);
}
@override
bool shouldRepaint(CirclePainter oldDelegate) =>
oldDelegate.color != color;
}
shouldRepaint bestimmt, ob der CustomPainter neu gezeichnet werden muss. Geben Sie nur dann true zurück, wenn sich die das Rendering beeinflussenden Daten ändern — Farbe, Größe, Diagrammdaten. RepaintBoundary isoliert das Neuzeichnen in eine separate Ebene — verwenden Sie es für Widgets, die sich selten ändern. Flutter hat kein setNeedsDisplay oder invalidate — das Neuzeichnen wird über setState oder ValueNotifier mit Änderungsüberwachung ausgelöst.
Flutter unterstützt LinearGradient, RadialGradient und SweepGradient — dieselben Typen wie in Android. Gradient erstellt einen Shader für Paint über createShader(Rect bounds). Transformationen werden über canvas.rotate, canvas.scale, canvas.translate und canvas.skew durchgeführt. Flutter verwendet eine 4x4-Transformationsmatrix (Matrix4) für das Transform-Widget. Zeichenanimationen in Flutter werden mit AnimationController in Verbindung mit setState zum Neuzeichnen des CustomPainter erstellt.
Die korrekte Messung benutzerdefinierter Views ist die Grundlage für ein vorhersagbares Oberflächenverhalten. Auf iOS wird die View-Größe über sizeThatFits und intrinsicContentSize bestimmt. sizeThatFits gibt die optimale Größe für gegebene Einschränkungen zurück. intrinsicContentSize — die natürliche Inhaltsgröße ohne externe Einschränkungen. Auf Android wird die Messung in onMeasure mit MeasureSpec-Parametern (UNSPECIFIED, EXACTLY, AT_MOST) implementiert. In Flutter wird die Größe an paint(Canvas, Size) übergeben und kann über computeDryLayout oder LayoutBuilder berechnet werden.
intrinsicContentSize gibt einen CGSize zurück — die natürliche Größe des View basierend auf seinem Inhalt. setContentHuggingPriority und setContentCompressionResistancePriority steuern das Verhalten beim Dehnen und Stauchen. sizeThatFits wird vom System aufgerufen, um die Größe im Auto Layout zu berechnen. Für benutzerdefinierte Views überschreiben Sie intrinsicContentSize, wenn Ihre Komponente eine natürliche Größe hat — zum Beispiel sollte ein Kreis immer 100x100 sein.
onMeasure akzeptiert widthMeasureSpec und heightMeasureSpec. MeasureSpec enthält Modus und Größe: UNSPECIFIED (keine Einschränkungen, View wählt eigene Größe), EXACTLY (genaue Größe vom Eltern-Element), AT_MOST (maximale Größe). setMeasuredDimension(width, height) speichert das Messergebnis. Bei Datenänderungen rufen Sie requestLayout() zur erneuten Messung auf. Verschachtelte ViewGroups erfordern das Überschreiben von onLayout zur Anordnung der Kind-Elemente.
| Plattform | Messmethode | Aufruf bei Änderung | Rückgabe |
|---|---|---|---|
| iOS | sizeThatFits / intrinsicContentSize | setNeedsLayout / invalidateIntrinsicContentSize | CGSize |
| Android | onMeasure / setMeasuredDimension | requestLayout / invalidate | void (speichert Größe) |
| Flutter | computeDryLayout | setState / LayoutBuilder | Size |
computeDryLayout ist eine RenderObject-Methode zur Berechnung der Größe ohne vollständigen Layout-Zyklus. LayoutBuilder.getSize — eine Alternative zum Abrufen des verfügbaren Platzes in der build-Methode. In Flutter wird die Leinwandgröße als Size an paint übergeben und erfordert keine separate Messung — CustomPainter zeichnet innerhalb der übergebenen Grenzen. Für benutzerdefinierte RenderObjects müssen Sie jedoch performLayout und computeDryLayout überschreiben.
Häufig gestellte Fragen
drawRect ist eine UIView-Methode für benutzerdefiniertes Zeichnen über Core Graphics. Es wird beim ersten Rendern des View und nach jedem setNeedsDisplay()-Aufruf aufgerufen. Verwenden Sie CGContext innerhalb von drawRect für Linien, Formen und Text.
Erstellen Sie eine Klasse, die View erweitert, überschreiben Sie onDraw(Canvas canvas) und verwenden Sie die Canvas-API: drawCircle, drawRect, drawPath. Paint konfiguriert Farbe, Stärke und Stil. Zum Aktualisieren rufen Sie invalidate() auf.
CustomPainter ist eine Flutter-Klasse für benutzerdefiniertes Zeichnen auf Canvas. Implementieren Sie die Methoden paint(Canvas, Size) und shouldRepaint. Es wird über das CustomPaint-Widget platziert. Flutter hat kein drawRect — alles Zeichnen erfolgt über CustomPainter.
Auf iOS verwenden Sie sizeThatFits und intrinsicContentSize. Auf Android — onMeasure mit MeasureSpec. In Flutter wird die Größe an paint(Canvas, Size) übergeben oder über computeDryLayout berechnet. Jede Plattform verwendet ihre eigene Messmethode.
Benutzerdefinierte Views werden für einzigartige Grafiken, Animationen, Diagramme und Elemente benötigt, die mit Standard-UIKit oder View nicht implementiert werden können. Für einfache Stile reicht es, Standardkomponenten zu konfigurieren — komplizieren Sie die Architektur nicht unnötig.
Zusammenfassung
Wir entwickeln eine mobile Applikation schlüsselfertig
IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.