Lors de la création d'une vue personnalisée, j'ai remarqué que de nombreuses personnes semblent le faire comme ceci:
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.
}
Ma première question est: qu'en est-il du constructeur MyView(Context context, AttributeSet attrs, int defStyle)
? Je ne sais pas où il est utilisé, mais je le vois dans la super classe. En ai-je besoin et où est-il utilisé?
Il y a une autre partie à cette question .
la source
Si vous remplacez les trois constructeurs, veuillez NE PAS CASCADEZ LES
this(...)
APPELS. Vous devriez plutôt faire ceci:La raison en est que la classe parente peut inclure des attributs par défaut dans ses propres constructeurs que vous risquez de remplacer accidentellement. Par exemple, voici le constructeur pour
TextView
:Si vous n'avez pas appelé
super(context)
, vous n'auriez pas correctement définiR.attr.textViewStyle
comme attr de style.la source
MyView (contexte contextuel)
Utilisé lors de l'instanciation de Views par programme.
MyView (contexte de contexte, attrs AttributeSet)
Utilisé par le
LayoutInflater
pour appliquer les attributs xml. Si l'un de ces attributs est nomméstyle
, les attributs seront recherchés dans le style avant de rechercher des valeurs explicites dans le fichier xml de mise en page.MyView (Contexte contextuel, AttributeSet attrs, int defStyleAttr)
Supposons que vous souhaitiez appliquer un style par défaut à tous les widgets sans avoir à le spécifier
style
dans chaque fichier de mise en page. Pour un exemple, rendez toutes les cases à cocher roses par défaut. Vous pouvez le faire avec defStyleAttr et le framework recherchera le style par défaut dans votre thème.Notez qu'il a
defStyleAttr
été mal nommé il y adefStyle
quelque temps et il y a une discussion pour savoir si ce constructeur est vraiment nécessaire ou non. Voir https://code.google.com/p/android/issues/detail?id=12683MyView (Contexte contextuel, AttributeSet attrs, int defStyleAttr, int defStyleRes)
Le 3ème constructeur fonctionne bien si vous contrôlez le thème de base des applications. Cela fonctionne pour Google car ils livrent leurs widgets avec les thèmes par défaut. Mais supposons que vous écriviez une bibliothèque de widgets et que vous souhaitiez qu'un style par défaut soit défini sans que vos utilisateurs aient besoin de modifier leur thème. Vous pouvez maintenant le faire
defStyleRes
en lui attribuant la valeur par défaut dans les 2 premiers constructeurs:En tout
Si vous implémentez vos propres vues, seuls les 2 premiers constructeurs devraient être nécessaires et peuvent être appelés par le framework.
Si vous voulez que vos vues soient extensibles, vous pouvez implémenter le 4ème constructeur pour les enfants de votre classe afin de pouvoir utiliser le style global.
Je ne vois pas de cas d'utilisation réel pour le 3ème constructeur. Peut-être un raccourci si vous ne fournissez pas de style par défaut pour votre widget, mais que vous souhaitez toujours que vos utilisateurs puissent le faire. Ça ne devrait pas arriver tant que ça.
la source
Kotlin semble enlever une grande partie de cette douleur:
@JvmOverloads générera tous les constructeurs requis (voir la documentation de cette annotation ), chacun appelant vraisemblablement super (). Ensuite, remplacez simplement votre méthode d'initialisation par un bloc Kotlin init {}. Le code de la chaudière est parti!
la source
Le troisième constructeur est beaucoup plus compliqué, laissez-moi vous donner un exemple.
Support-v7
SwitchCompact
prend en chargethumbTint
ettrackTint
attribut depuis la version 24 alors que la version 23 ne les prend pas en charge.Maintenant, vous voulez les prendre en charge dans la version 23 et comment ferez-vous pour y parvenir?Nous supposons que vous utilisez des
SupportedSwitchCompact
extensions de vue personnaliséesSwitchCompact
.C'est un style de code traditionnel. Notez que nous passons 0 au troisième paramètre ici . Lorsque vous exécutez le code, vous trouverez
getThumbDrawable()
toujours return null à quel point il est étrange car la méthodegetThumbDrawable()
est la méthode de sa super classeSwitchCompact
.Si vous passez
R.attr.switchStyle
au troisième paramètre, tout se passe bien, alors pourquoi?Le troisième paramètre est un attribut simple. L'attribut pointe vers une ressource de style. Dans le cas ci-dessus, le système trouvera l'
switchStyle
attribut dans le thème courant, heureusement que le système le trouve.Dans
frameworks/base/core/res/res/values/themes.xml
, vous verrez:la source
Si vous devez inclure trois constructeurs comme celui en cours de discussion, vous pouvez également le faire.
la source