Comment: Définir élément thème (style) pour widget personnalisé
-
12-10-2019 - |
Question
J'ai écrit un widget personnalisé pour un contrôle que nous utilisons largement dans notre application. La dérive de la classe widget de ImageButton
et il étend dans quelques moyens simples. J'ai défini un style que je peux appliquer au widget comme il est utilisé, mais je préfère le mettre en place à travers un thème. En R.styleable
je vois les attributs de style comme widget imageButtonStyle
et textViewStyle
. Est-il possible de créer quelque chose comme ce widget pour l'usage que j'ai écrit?
La solution
Oui, il y a une façon:
Supposons que vous avez une déclaration d'attributs pour votre widget (en attrs.xml
):
<declare-styleable name="CustomImageButton">
<attr name="customAttr" format="string"/>
</declare-styleable>
Déclarer un attribut que vous utiliserez pour une référence de style (en attrs.xml
):
<declare-styleable name="CustomTheme">
<attr name="customImageButtonStyle" format="reference"/>
</declare-styleable>
déclarer un ensemble de valeurs d'attributs par défaut pour le widget (en styles.xml
):
<style name="Widget.ImageButton.Custom" parent="android:style/Widget.ImageButton">
<item name="customAttr">some value</item>
</style>
Déclarer un thème personnalisé (en themes.xml
):
<style name="Theme.Custom" parent="@android:style/Theme">
<item name="customImageButtonStyle">@style/Widget.ImageButton.Custom</item>
</style>
Utilisez cet attribut comme troisième argument dans le constructeur de votre widget (en CustomImageButton.java
):
public class CustomImageButton extends ImageButton {
private String customAttr;
public CustomImageButton( Context context ) {
this( context, null );
}
public CustomImageButton( Context context, AttributeSet attrs ) {
this( context, attrs, R.attr.customImageButtonStyle );
}
public CustomImageButton( Context context, AttributeSet attrs,
int defStyle ) {
super( context, attrs, defStyle );
final TypedArray array = context.obtainStyledAttributes( attrs,
R.styleable.CustomImageButton, defStyle,
R.style.Widget_ImageButton_Custom ); // see below
this.customAttr =
array.getString( R.styleable.CustomImageButton_customAttr, "" );
array.recycle();
}
}
Maintenant, vous devez appliquer Theme.Custom
à toutes les activités que l'utilisation CustomImageButton
(en AndroidManifest.xml):
<activity android:name=".MyActivity" android:theme="@style/Theme.Custom"/>
C'est tout. Maintenant CustomImageButton
tente de charger les valeurs d'attributs par défaut d'attribut customImageButtonStyle
du thème actuel. Si aucun tel attribut se trouve dans le thème ou la valeur d'attribut est @null
alors l'argument final obtainStyledAttributes
sera utilisé. Widget.ImageButton.Custom
dans ce cas
Vous pouvez modifier les noms de toutes les instances et tous les fichiers (sauf AndroidManifest.xml
), mais il serait préférable d'utiliser Android convention de nommage.
Autres conseils
Un autre aspect en plus d'une excellente réponse de michael est prépondérant attributs personnalisés dans les thèmes. Supposons que vous avez un certain nombre de vues personnalisées que tous se réfèrent à l'attribut personnalisé « de custom_background ».
<declare-styleable name="MyCustomStylables">
<attr name="custom_background" format="color"/>
</declare-styleable>
Dans un thème que vous définissez ce que la valeur est
<style name="MyColorfulTheme" parent="AppTheme">
<item name="custom_background">#ff0000</item>
</style>
ou
<style name="MyBoringTheme" parent="AppTheme">
<item name="custom_background">#ffffff</item>
</style>
Vous pouvez vous référer à l'attribut dans un style
<style name="MyDefaultLabelStyle" parent="AppTheme">
<item name="android:background">?background_label</item>
</style>
Notez le point d'interrogation, comme également utilisé pour référence attribut android comme dans
?android:attr/colorBackground
Comme vous l'avez remarqué, vous pouvez probablement -et références utilisation de doit si @color au lieu de couleurs codées en dur.
Alors pourquoi ne pas simplement faire
<item name="android:background">@color/my_background_color</item>
Vous ne pouvez pas modifier la définition de « my_background_color » lors de l'exécution, alors que vous pouvez facilement changer de thème.