Ansichtsklasse erstellen

Funktion „Schreiben“ ausprobieren
Jetpack Compose ist das empfohlene UI-Toolkit für Android. Hier erfahren Sie, wie Sie in der Funktion „Compose“ mit Layouts arbeiten.

Eine gut konzipierte benutzerdefinierte Ansicht ist mit jeder anderen gut konzipierten Klasse vergleichbar. Sie kapselt einen bestimmten Satz von Funktionen mit einer einfachen Oberfläche, nutzt CPU und Arbeitsspeicher effizient und so weiter. Zusätzlich zu einer gut konzipierten Klasse muss eine benutzerdefinierte Ansicht folgende Voraussetzungen erfüllen:

  • Entspricht den Android-Standards.
  • Stellen Sie benutzerdefinierte Style-Attribute bereit, die mit Android-XML-Layouts funktionieren.
  • Ereignisse zur Barrierefreiheit senden.
  • Es muss mit mehreren Android-Plattformen kompatibel sein.

Das Android-Framework bietet eine Reihe von Basisklassen und XML-Tags, mit denen Sie eine Ansicht erstellen können, die all diese Anforderungen erfüllt. In dieser Lektion wird erläutert, wie Sie mit dem Android-Framework die Hauptfunktion einer Ansichtsklasse erstellen.

Weitere Informationen finden Sie unter Komponenten der benutzerdefinierten Ansicht.

Unterklassen für Datenansichten erstellen

Alle im Android-Framework definierten Ansichtsklassen erweitern View. Mit der benutzerdefinierten Ansicht können Sie View auch direkt erweitern oder Sie sparen Zeit, indem Sie eine der vorhandenen Unterklassen der Ansicht, z. B. Button, erweitern.

Damit Android Studio mit Ihrer Ansicht interagieren kann, müssen Sie mindestens einen Konstruktor angeben, der ein Context- und ein AttributeSet-Objekt als Parameter verwendet. Mit diesem Konstruktor kann der Layout-Editor eine Instanz Ihrer Ansicht erstellen und bearbeiten.

Kotlin

class PieChart(context: Context, attrs: AttributeSet) : View(context, attrs)

Java

class PieChart extends View {
    public PieChart(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
}

Benutzerdefinierte Attribute definieren

Wenn Sie Ihrer Benutzeroberfläche ein integriertes View hinzufügen möchten, geben Sie es in einem XML-Element an und steuern Sie seine Darstellung und sein Verhalten mit Elementattributen. Sie können benutzerdefinierte Ansichten auch mithilfe von XML hinzufügen und gestalten. So aktivieren Sie dieses Verhalten in der benutzerdefinierten Ansicht:

  • Definieren Sie benutzerdefinierte Attribute für Ihre Ansicht in einem <declare-styleable> -Ressourcenelement.
  • Geben Sie Werte für die Attribute in Ihrem XML-Layout an.
  • Attributwerte zur Laufzeit abrufen.
  • Wenden Sie die abgerufenen Attributwerte auf Ihre Ansicht an.

In diesem Abschnitt wird erläutert, wie Sie benutzerdefinierte Attribute definieren und ihre Werte angeben. Im nächsten Abschnitt geht es um das Abrufen und Anwenden der Werte zur Laufzeit.

Fügen Sie Ihrem Projekt <declare-styleable> Ressourcen hinzu, um benutzerdefinierte Attribute zu definieren. In der Regel werden diese Ressourcen in einer res/values/attrs.xml-Datei gespeichert. Hier ein Beispiel für eine attrs.xml-Datei:

<resources>
   <declare-styleable name="PieChart">
       <attr name="showText" format="boolean" />
       <attr name="labelPosition" format="enum">
           <enum name="left" value="0"/>
           <enum name="right" value="1"/>
       </attr>
   </declare-styleable>
</resources>

Dieser Code deklariert zwei benutzerdefinierte Attribute, showText und labelPosition, die zu einer styleablen Entität namens PieChart gehören. Der Name der styleablen Entität entspricht Konventionsgemäß dem Namen der Klasse, die die benutzerdefinierte Ansicht definiert. Es ist zwar nicht notwendig, dieser Konvention zu folgen, viele gängige Code-Editoren sind jedoch bei der Vervollständigung von Anweisungen auf diese Namenskonvention angewiesen.

Nachdem Sie benutzerdefinierte Attribute definiert haben, können Sie sie wie integrierte Attribute in Layout-XML-Dateien verwenden. Der einzige Unterschied besteht darin, dass Ihre benutzerdefinierten Attribute zu einem anderen Namespace gehören. Sie gehören nicht zum Namespace http://schemas.android.com/apk/res/android, sondern zu http://schemas.android.com/apk/res/[your package name]. So verwenden Sie beispielsweise die für PieChart definierten Attribute:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:custom="http://schemas.android.com/apk/res-auto">
 <com.example.customviews.charting.PieChart
     custom:showText="true"
     custom:labelPosition="left" />
</LinearLayout>

Im Beispiel wird die Anweisung xmlns verwendet, damit der lange Namespace-URI nicht wiederholt werden muss. Diese Anweisung weist dem Namespace http://schemas.android.com/apk/res/com.example.customviews den Alias custom zu. Sie können einen beliebigen Alias für Ihren Namespace auswählen.

Beachten Sie den Namen des XML-Tags, mit dem die benutzerdefinierte Ansicht dem Layout hinzugefügt wird. Es ist der voll qualifizierte Name der benutzerdefinierten Ansichtsklasse. Wenn die Ansichtsklasse eine innere Klasse ist, qualifizieren Sie sie mit dem Namen der äußeren Klasse der Ansicht. Die Klasse PieChart hat beispielsweise eine innere Klasse namens PieView. Um die benutzerdefinierten Attribute aus dieser Klasse zu nutzen, verwenden Sie das Tag com.example.customviews.charting.PieChart$PieView.

Benutzerdefinierte Attribute anwenden

Wenn eine Ansicht über ein XML-Layout erstellt wird, werden alle Attribute im XML-Tag aus dem Ressourcen-Bundle gelesen und als AttributeSet an den Konstruktor der Ansicht übergeben. Es ist zwar möglich, Werte direkt aus AttributeSet zu lesen, aber dies hat einige Nachteile:

  • Ressourcenverweise innerhalb von Attributwerten werden nicht aufgelöst.
  • Stile werden nicht angewendet.

Übergeben Sie stattdessen AttributeSet an obtainStyledAttributes(). Diese Methode gibt ein TypedArray-Array mit Werten zurück, die bereits dereferenziert und formatiert sind.

Der Android-Ressourcen-Compiler nimmt Ihnen viel Arbeit ab, um den Aufruf von obtainStyledAttributes() zu vereinfachen. Für jede <declare-styleable>-Ressource im res/-Verzeichnis definiert die generierte R.java sowohl ein Array von Attribut-IDs als auch eine Reihe von Konstanten, die den Index für jedes Attribut im Array definieren. Sie verwenden die vordefinierten Konstanten, um die Attribute aus TypedArray zu lesen. So liest die Klasse PieChart ihre Attribute:

Kotlin

init {
    context.theme.obtainStyledAttributes(
            attrs,
            R.styleable.PieChart,
            0, 0).apply {

        try {
            mShowText = getBoolean(R.styleable.PieChart_showText, false)
            textPos = getInteger(R.styleable.PieChart_labelPosition, 0)
        } finally {
            recycle()
        }
    }
}

Java

public PieChart(Context context, AttributeSet attrs) {
   super(context, attrs);
   TypedArray a = context.getTheme().obtainStyledAttributes(
        attrs,
        R.styleable.PieChart,
        0, 0);

   try {
       mShowText = a.getBoolean(R.styleable.PieChart_showText, false);
       textPos = a.getInteger(R.styleable.PieChart_labelPosition, 0);
   } finally {
       a.recycle();
   }
}

Beachten Sie, dass TypedArray-Objekte eine gemeinsam genutzte Ressource sind und nach der Verwendung recycelt werden müssen.

Properties und Ereignisse hinzufügen

Attribute sind eine leistungsstarke Möglichkeit, das Verhalten und das Aussehen von Ansichten zu steuern. Sie können jedoch nur gelesen werden, wenn die Ansicht initialisiert wird. Um dynamisches Verhalten zu ermöglichen, stellen Sie für jedes benutzerdefinierte Attribut ein Attribut-Getter- und -Setter-Paar bereit. Das folgende Snippet zeigt, wie PieChart eine Eigenschaft namens showText verfügbar macht:

Kotlin

fun isShowText(): Boolean {
    return mShowText
}

fun setShowText(showText: Boolean) {
    mShowText = showText
    invalidate()
    requestLayout()
}

Java

public boolean isShowText() {
   return mShowText;
}

public void setShowText(boolean showText) {
   mShowText = showText;
   invalidate();
   requestLayout();
}

Mit setShowText werden invalidate() und requestLayout() aufgerufen. Diese Aufrufe sind entscheidend für ein zuverlässiges Verhalten der Ansicht. Sie müssen die Ansicht nach jeder Änderung an ihren Eigenschaften entwerten, die ihr Aussehen ändern könnte, damit das System weiß, dass sie neu gezeichnet werden muss. Ebenso müssen Sie ein neues Layout anfordern, wenn sich eine Eigenschaft in einer Weise ändert, die sich auf die Größe oder Form der Ansicht auswirken könnte. Wenn diese Methodenaufrufe entfernt werden, kann das zu schwer zu findenden Fehlern führen.

Benutzerdefinierte Ansichten müssen auch Event-Listener unterstützen, damit wichtige Ereignisse kommuniziert werden können. Beispielsweise macht PieChart ein benutzerdefiniertes Ereignis namens OnCurrentItemChanged verfügbar, um Listener darüber zu informieren, dass der Nutzer das Kreisdiagramm gedreht hat, um den Fokus auf ein neues Kreissegment zu legen.

Es kann leicht vergessen, Eigenschaften und Ereignisse verfügbar zu machen, insbesondere wenn Sie der einzige Nutzer der benutzerdefinierten Ansicht sind. Wenn Sie die Schnittstelle der Ansicht sorgfältig definieren, senken Sie zukünftige Wartungskosten. Es empfiehlt sich, immer alle Eigenschaften verfügbar zu machen, die sich auf die sichtbare Darstellung oder das Verhalten der benutzerdefinierten Ansicht auswirken.

Barrierefreies Design

Ihre benutzerdefinierte Ansicht muss eine große Bandbreite von Nutzern unterstützen. Dazu gehören auch Nutzer mit Beeinträchtigungen, die sie daran hindern, einen Touchscreen zu sehen oder zu verwenden. So unterstützen Sie Nutzer mit Beeinträchtigungen:

  • Verwenden Sie das Attribut android:contentDescription, um die Eingabefelder mit Labels zu versehen.
  • Senden Sie Ereignisse zu Bedienungshilfen, indem Sie gegebenenfalls sendAccessibilityEvent() aufrufen.
  • Unterstützen Sie alternative Controller, z. B. Steuerkreuze oder Trackballs.

Weitere Informationen zum Erstellen barrierefreier Ansichten finden Sie unter Apps barrierefreier gestalten.