Beim Erstellen einer benutzerdefinierten Ansicht ist mir aufgefallen, dass viele Benutzer dies anscheinend so tun:
public MyView(Context context) {
super(context);
// this constructor used when programmatically creating view
doAdditionalConstructorWork();
}
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
// this constructor used when creating view through XML
doAdditionalConstructorWork();
}
private void doAdditionalConstructorWork() {
// init variables etc.
}
Meine erste Frage ist, was ist mit dem Konstruktor MyView(Context context, AttributeSet attrs, int defStyle)
? Ich bin nicht sicher, wo es verwendet wird, aber ich sehe es in der Superklasse. Brauche ich es und wo wird es verwendet?
Diese Frage hat noch einen weiteren Teil .
quelle
Wenn Sie alle drei Konstruktoren überschreiben, CASCADE
this(...)
CALLS NICHT . Sie sollten stattdessen Folgendes tun:Der Grund dafür ist, dass die übergeordnete Klasse möglicherweise Standardattribute in ihren eigenen Konstruktoren enthält, die Sie möglicherweise versehentlich überschreiben. Dies ist beispielsweise der Konstruktor für
TextView
:Wenn Sie nicht angerufen hätten
super(context)
, hätten SieR.attr.textViewStyle
den Stil attr nicht richtig eingestellt .quelle
MyView (Kontextkontext)
Wird verwendet, wenn Ansichten programmgesteuert instanziiert werden.
MyView (Kontextkontext, AttributeSet-Attribute)
Wird von verwendet
LayoutInflater
, um XML-Attribute anzuwenden. Wenn eines dieser Attribute benannt iststyle
, werden die Attribute im Stil nachgeschlagen, bevor nach expliziten Werten in der XML-Layoutdatei gesucht wird.MyView (Kontextkontext, AttributeSet-Attribute, int defStyleAttr)
Angenommen, Sie möchten einen Standardstil auf alle Widgets anwenden, ohne dies
style
in jeder Layoutdatei angeben zu müssen. Zum Beispiel lassen Sie alle Kontrollkästchen standardmäßig rosa werden. Sie können dies mit defStyleAttr tun, und das Framework sucht nach dem Standardstil in Ihrem Thema.Beachten Sie, dass dies
defStyleAttr
vordefStyle
einiger Zeit falsch benannt wurde und es einige Diskussionen darüber gibt, ob dieser Konstruktor wirklich benötigt wird oder nicht. Siehe https://code.google.com/p/android/issues/detail?id=12683MyView (Kontextkontext, AttributeSet-Attribute, int defStyleAttr, int defStyleRes)
Der 3. Konstruktor funktioniert gut, wenn Sie die Kontrolle über das Basisthema der Anwendungen haben. Das funktioniert bei Google, weil sie ihre Widgets neben den Standardthemen versenden. Angenommen, Sie schreiben eine Widget-Bibliothek und möchten, dass ein Standardstil festgelegt wird, ohne dass Ihre Benutzer ihr Thema anpassen müssen. Sie können dies jetzt tun,
defStyleRes
indem Sie es in den beiden ersten Konstruktoren auf den Standardwert setzen:Alles in allem
Wenn Sie Ihre eigenen Ansichten implementieren, sollten nur die beiden ersten Konstruktoren benötigt werden und können vom Framework aufgerufen werden.
Wenn Sie möchten, dass Ihre Ansichten erweiterbar sind, implementieren Sie möglicherweise den 4. Konstruktor, damit Kinder Ihrer Klasse das globale Styling verwenden können.
Ich sehe keinen wirklichen Anwendungsfall für den 3. Konstruktor. Möglicherweise eine Verknüpfung, wenn Sie keinen Standardstil für Ihr Widget angeben und dennoch möchten, dass Ihre Benutzer dies tun können. Sollte nicht so viel passieren.
quelle
Kotlin scheint viel von diesem Schmerz wegzunehmen:
@JvmOverloads generiert alle erforderlichen Konstruktoren (siehe Dokumentation dieser Annotation ), von denen jeder vermutlich super () aufruft. Ersetzen Sie dann einfach Ihre Initialisierungsmethode durch einen Kotlin init {} -Block. Boilerplate-Code weg!
quelle
Der dritte Konstruktor ist viel komplizierter. Lassen Sie mich ein Beispiel geben.
Support-v7-
SwitchCompact
Paket unterstütztthumbTint
undtrackTint
Attribute seit 24 Version, während 23 Version sie nicht unterstützt. Jetzt möchten Sie sie in 23 Version unterstützen und wie werden Sie dies erreichen?Wir gehen davon aus Gewohnheit verwenden Ansicht
SupportedSwitchCompact
erstrecktSwitchCompact
.Es ist ein traditioneller Codestil. Beachten Sie, dass wir hier 0 an den dritten Parameter übergeben . Wenn Sie den Code ausführen, werden Sie
getThumbDrawable()
immer null zurückgeben, wie seltsam es ist, weil die Methode die MethodegetThumbDrawable()
ihrer Superklasse istSwitchCompact
.Wenn Sie
R.attr.switchStyle
zum dritten Parameter übergehen , läuft alles gut. Warum also?Der dritte Parameter ist ein einfaches Attribut. Das Attribut verweist auf eine Stilressource. Im obigen Fall findet das System das
switchStyle
Attribut im aktuellen Thema. Glücklicherweise findet das System es.In sehen
frameworks/base/core/res/res/values/themes.xml
Sie:quelle
Wenn Sie drei Konstruktoren wie den jetzt diskutierten einschließen müssen, können Sie dies auch tun.
quelle