Wie deklariere ich ein Android-UI-Element mithilfe von XML?
xml
android
user-interface
Casebash
quelle
quelle
Antworten:
Das Android-Entwicklerhandbuch enthält einen Abschnitt namens Erstellen benutzerdefinierter Komponenten . Leider ist die Diskussion der XML-Attribute nur das Deklarieren des Steuerelements in der Layoutdatei und nicht das tatsächliche Behandeln der Werte in der Klasseninitialisierung. Die Schritte sind wie folgt:
1. Deklarieren Sie Attribute in
values\attrs.xml
Beachten Sie die Verwendung eines nicht qualifizierten Namens im
declare-styleable
Tag. Nicht standardmäßige Android-Attribute wieextraInformation
müssen ihren Typ deklarieren lassen. In der Oberklasse deklarierte Tags sind in Unterklassen verfügbar, ohne dass sie erneut deklariert werden müssen.2. Erstellen Sie Konstruktoren
Da es zwei Konstruktoren gibt, die eine
AttributeSet
für die Initialisierung verwenden, ist es zweckmäßig, eine separate Initialisierungsmethode zu erstellen, die die Konstruktoren aufrufen können.R.styleable.MyCustomView
ist eine automatisch generierteint[]
Ressource, bei der jedes Element die ID eines Attributs ist. Attribute werden für jede Eigenschaft im XML generiert, indem der Attributname an den Elementnamen angehängt wird. Zum BeispielR.styleable.MyCustomView_android_text
enthält dasandroid_text
Attribut fürMyCustomView
. Attribute können dannTypedArray
mit verschiedenenget
Funktionen aus dem abgerufen werden . Wenn das Attribut nicht im XML definiert ist,null
wird es zurückgegeben. Außer natürlich, wenn der Rückgabetyp ein Grundelement ist. In diesem Fall wird das zweite Argument zurückgegeben.Wenn Sie nicht alle Attribute abrufen möchten, können Sie dieses Array manuell erstellen. Die ID für Standard-Android-Attribute ist enthalten
android.R.attr
, während Attribute für dieses Projekt enthalten sindR.attr
.Bitte beachten Sie, dass Sie sollten nicht alles in Verwendung
android.R.styleable
, gemäß diesem Thread es in Zukunft ändern kann. Es ist immer noch in der Dokumentation enthalten, dass es nützlich ist, alle diese Konstanten an einem Ort anzuzeigen.3. Verwenden Sie es in Layoutdateien wie
layout\main.xml
Fügen Sie die Namespace-Deklaration
xmlns:app="http://schemas.android.com/apk/res-auto"
in das XML-Element der obersten Ebene ein. Namespaces bieten eine Methode, um Konflikte zu vermeiden, die manchmal auftreten, wenn verschiedene Schemas dieselben Elementnamen verwenden ( weitere Informationen finden Sie in diesem Artikel ). Die URL ist einfach eine Möglichkeit , Schemas eindeutig zu identifizieren - unter dieser URL muss eigentlich nichts gehostet werden . Wenn dies anscheinend nichts bewirkt, müssen Sie das Namespace-Präfix nur hinzufügen, wenn Sie einen Konflikt lösen müssen.Verweisen Sie auf die benutzerdefinierte Ansicht mit dem vollständig qualifizierten Namen.
Android LabelView-Beispiel
Wenn Sie ein vollständiges Beispiel wünschen, schauen Sie sich das Beispiel für die Android-Etikettenansicht an.
LabelView.java
attrs.xml
custom_view_1.xml
Dies ist in a
LinearLayout
mit einem Namespace-Attribut enthalten:xmlns:app="http://schemas.android.com/apk/res-auto"
Links
quelle
Tolle Referenz. Vielen Dank! Eine Ergänzung dazu:
Wenn zufällig ein Bibliotheksprojekt enthalten ist, das benutzerdefinierte Attribute für eine benutzerdefinierte Ansicht deklariert hat, müssen Sie Ihren Projektnamespace deklarieren, nicht den der Bibliothek. Z.B:
Vorausgesetzt, die Bibliothek hat das Paket "com.example.library.customview" und das Arbeitsprojekt hat das Paket "com.example.customview", dann:
Funktioniert nicht (zeigt den Fehler "Fehler: Keine Ressourcen-ID für Attribut 'newAttr' im Paket 'com.example.library.customview' gefunden"):
Wird funktionieren:
quelle
xmlns:app="http://schemas.android.com/apk/res-auto"
Siehe Kommentar 57 in code.google.com/p/android/issues/detail?id=9656Suspicious namespace: Did you mean http://schemas.android.com/apk/res-auto
res-auto
dass wir Android Studio und Gradle verwenden. Andernfalls (z. B. einige Eclipse-Versionen) würde es normalerweise endenlib/[your package name]
. dhhttp://schemas.android.com/apk/lib/[your package name]
Ergänzung zu den am häufigsten gewählten Antworten.
getStyledAttributes ()
Ich möchte einige Wörter zur Verwendung von getStyledAttributes () hinzufügen, wenn wir eine benutzerdefinierte Ansicht mit den definierten Attributen android: xxx erstellen. Besonders wenn wir TextAppearance verwenden.
Wie in "2. Erstellen von Konstruktoren" erwähnt, erhält die benutzerdefinierte Ansicht bei ihrer Erstellung AttributeSet. Die Hauptverwendung finden Sie im TextView-Quellcode (API 16).
Was können wir hier sehen?
obtainStyledAttributes(AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes)
Der Attributsatz wird gemäß der Dokumentation thematisch verarbeitet. Attributwerte werden Schritt für Schritt zusammengestellt. Zuerst werden Attribute aus dem Thema gefüllt, dann werden Werte durch Werte aus dem Stil ersetzt, und schließlich ersetzen exakte Werte aus XML für eine spezielle Ansichtsinstanz andere.
Array angeforderter Attribute -
com.android.internal.R.styleable.TextView
Dies ist ein gewöhnliches Array von Konstanten. Wenn wir Standardattribute anfordern, können wir dieses Array manuell erstellen.
Was in der Dokumentation nicht erwähnt wird - Reihenfolge der Ergebnisse TypedArray-Elemente.
Wenn die benutzerdefinierte Ansicht in attrs.xml deklariert wird, werden spezielle Konstanten für Attributindizes generiert. Und wir können Werte folgendermaßen extrahieren :
a.getString(R.styleable.MyCustomView_android_text)
. Aber für das Handbuchint[]
gibt es jedoch keine Konstanten. Ich nehme an, dass getXXXValue (arrayIndex) gut funktioniert.Eine andere Frage lautet: "Wie können wir interne Konstanten ersetzen und Standardattribute anfordern?" Wir können android.R.attr. * Werte verwenden.
Wenn wir also das Standardattribut TextAppearance in der benutzerdefinierten Ansicht verwenden und seine Werte im Konstruktor lesen möchten, können wir den Code aus TextView folgendermaßen ändern:
Wo CustomLabel definiert ist:
Vielleicht irre ich mich irgendwie, aber die Android-Dokumentation zu getStyledAttributes () ist sehr schlecht.
Standard-UI-Komponente erweitern
Gleichzeitig können wir einfach die Standard-UI-Komponente unter Verwendung aller deklarierten Attribute erweitern. Dieser Ansatz ist nicht so gut, weil beispielsweise TextView viele Eigenschaften deklariert. Und es wird unmöglich sein, die volle Funktionalität beim Überschreiben von onMeasure () und onDraw () zu implementieren.
Wir können jedoch die theoretisch weite Wiederverwendung von benutzerdefinierten Komponenten opfern. Sagen Sie "Ich weiß genau, welche Funktionen ich verwenden werde" und geben Sie keinen Code an Dritte weiter.
Dann können wir den Konstruktor implementieren
CustomComponent(Context, AttributeSet, defStyle)
. Nach dem Aufrufsuper(...)
werden alle Attribute analysiert und über Getter-Methoden verfügbar sein.quelle
Es scheint, dass Google seine Entwicklerseite aktualisiert und dort verschiedene Schulungen hinzugefügt hat.
Einer von ihnen beschäftigt sich mit der Erstellung von benutzerdefinierten Ansichten und können gefunden werden hier
quelle
Vielen Dank für die erste Antwort.
Ich hatte nur ein Problem damit. Beim Aufblasen meiner Ansicht hatte ich einen Fehler: java.lang.NoSuchMethodException: MyView (Kontext, Attribute)
Ich habe es gelöst, indem ich einen neuen Konstruktor erstellt habe:
Hoffe das wird helfen!
quelle
Sie können jede Layoutdatei in eine andere Layoutdatei aufnehmen.
Hier sind die Layoutdateien im Include-Tag andere XML-Layoutdateien im selben res-Ordner.
quelle