Comment dois-je déclarer un Android élément de l'INTERFACE utilisateur à l'aide de XML?
Réponses
Trop de publicités?L'Android Developer Guide a une section appelée la Construction de Composants Personnalisés. Malheureusement, la discussion des attributs XML ne couvre que de déclarer le contrôle à l'intérieur du fichier de mise en page et pas vraiment de la manipulation de la valeurs à l'intérieur de la classe d'initialisation. Les étapes sont comme suit:
1. Déclarer des attributs en values\attrs.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="MyCustomView">
<attr name="android:text"/>
<attr name="android:textColor"/>
<attr name="extraInformation" format="string" />
</declare-styleable>
</resources>
Notez l'utilisation d'un nom non qualifié dans l' declare-styleable
balise. Non-standard android attributs comme extraInformation
ont besoin d'avoir leur type déclaré. Tags déclaré dans la super-classe sera disponible dans les sous-classes sans avoir à être redéclarée.
2. Créer constructeurs
Puisqu'il y a deux constructeurs qui utilisent un AttributeSet
pour l'initialisation, il est commode de créer une méthode d'initialisation pour les constructeurs de faire appel.
private void init(AttributeSet attrs) {
TypedArray a=getContext().obtainStyledAttributes(
attrs,
R.styleable.MyCustomView);
//Use a
Log.i("test",a.getString(
R.styleable.MyCustomView_android_text));
Log.i("test",""+a.getColor(
R.styleable.MyCustomView_android_textColor, Color.BLACK));
Log.i("test",a.getString(
R.styleable.MyCustomView_extraInformation));
//Don't forget this
a.recycle();
}
R.styleable.MyCustomView
est générée automatiquement int[]
de ressources où chaque élément est l'ID d'un attribut. Les attributs sont générés pour chaque propriété dans le fichier XML en ajoutant le nom de l'attribut le nom de l'élément. Par exemple, R.styleable.MyCustomView_android_text
contient de l' android_text
d'attribut pour MyCustomView
. Les attributs peuvent être récupérées à partir de l' TypedArray
à l'aide de divers get
fonctions. Si l'attribut n'est pas défini dans la défini dans le fichier XML, puis null
est retourné. Sauf, bien sûr, si le type de retour est un primitif, auquel cas le second argument est renvoyé.
Si vous ne voulez pas de récupérer tous les attributs, il est possible de créer ce tableau manuellement.L'ID pour android standard attributs sont inclus dans android.R.attr
, tandis que les attributs de ce projet sont en R.attr
.
int attrsWanted[]=new int[]{android.R.attr.text, R.attr.textColor};
Veuillez noter que vous devez ne pas utiliser quoi que ce soit en android.R.styleable
, conformément à ce fil, il peut changer dans l'avenir. Il est encore dans la documentation comme étant à la vue de tous ces constantes dans le est utile.
3. L'utiliser dans une mise en page des fichiers tels que layout\main.xml
Inclure la déclaration d'espace de noms xmlns:app="http://schemas.android.com/apk/res-auto"
dans le niveau supérieur de l'élément xml. Les espaces de noms de fournir une méthode pour éviter les conflits qui se produisent parfois lors de différents schémas d'utiliser les mêmes noms d'élément (voir cet article pour plus d'infos). L'URL est tout simplement une manière de l'identification univoque des schémas - rien n'a réellement besoin d'être hébergé à l'URL. Si cela ne semble pas faire quoi que ce soit, c'est parce que vous n'avez pas besoin d'ajouter le préfixe d'espace de noms si vous en avez besoin pour résoudre un conflit.
<com.mycompany.projectname.MyCustomView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@android:color/transparent"
android:text="Test text"
android:textColor="#FFFFFF"
app:extraInformation="My extra information"
/>
Référence de la vue personnalisée à l'aide du nom complet.
Android LabelView Échantillon
Si vous voulez un exemple complet, regarder le android étiquette de vue de l'échantillon.
TypedArray a=context.obtainStyledAttributes(attrs, R.styleable.LabelView);
CharSequences=a.getString(R.styleable.LabelView_text);
<declare-styleable name="LabelView">
<attr name="text"format="string"/>
<attr name="textColor"format="color"/>
<attr name="textSize"format="dimension"/>
</declare-styleable>
<com.example.android.apis.view.LabelView
android:background="@drawable/blue"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
app:text="Blue" app:textSize="20dp"/>
C'est contenue dans un LinearLayout
avec un espace de noms d'attribut: xmlns:app="http://schemas.android.com/apk/res-auto"
Liens
Grande référence. Merci! Un plus:
Si vous avez un projet de bibliothèque inclus qui a déclaré attributs personnalisés pour un affichage personnalisé, vous devez déclarer votre projet d'espace de noms, pas de la bibliothèque. Par exemple:
Étant donné que la bibliothèque a le package "com.exemple.de la bibliothèque.customview" et le projet de travail a le package "com.exemple.customview", puis:
Ne fonctionnera pas (affiche le message d'erreur " erreur: Aucun identificateur de ressource trouvé pour l'attribut 'newAttr' dans le paquet 'com.exemple.de la bibliothèque.customview'" ):
<com.library.CustomView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res/com.example.library.customview"
android:id="@+id/myView"
app:newAttr="value" />
Fonctionne:
<com.library.CustomView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res/com.example.customview"
android:id="@+id/myView"
app:newAttr="value" />
Outre le plus de vote réponse.
obtainStyledAttributes()
Je veux ajouter quelques mots à propos de obtainStyledAttributes() utilisation, lorsque nous avons créer un affichage personnalisé à l'aide de android:xxx prdefined attributs. Surtout lorsque nous utilisons TextAppearance.
Comme il a été mentionné dans la section "2. La création des constructeurs", affichage personnalisé obtient AttributeSet sur sa création. Principale utilisation, nous pouvons voir dans le TextView code source de l'API (16).
final Resources.Theme theme = context.getTheme();
// TextAppearance is inspected first, but let observe it later
TypedArray a = theme.obtainStyledAttributes(
attrs, com.android.internal.R.styleable.TextView, defStyle, 0);
int n = a.getIndexCount();
for (int i = 0; i < n; i++)
{
int attr = a.getIndex(i);
// huge switch with pattern value=a.getXXX(attr) <=> a.getXXX(a.getIndex(i))
}
a.recycle();
Ce que nous pouvons voir ici?obtainStyledAttributes(AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes)
L'attribut est traitée par thème en fonction de la documentation. Les valeurs d'attribut sont compilés étape par étape. Attributs premiers sont remplis de thème, puis les valeurs sont remplacées par des valeurs de style, et enfin les valeurs exactes de XML pour l'affichage spécial instance de remplacer d'autres.
Tableau des attributs - com.android.internal.R.styleable.TextView
C'est un tableau ordinaire de constantes. Si nous demandons aux attributs standard, nous pouvons construire ce tableau manuellement.
Ce n'est pas mentionnée dans la documentation d'ordre de résultat TypedArray éléments.
Lors de l'affichage personnalisé est déclaré dans attrs.xml, des constantes spéciales pour l'attribut index sont générés. Et l'on peut extraire des valeurs de cette façon: a.getString(R.styleable.MyCustomView_android_text)
. Mais pour manuel int[]
il n'existe pas de constantes. Je suppose, que getXXXValue(arrayIndex) fonctionnent bien.
Et l'autre question est: "Comment nous pouvons remplacer internes constantes, et demande attributs standard?" Nous pouvons utiliser android.R.attr.* des valeurs.
Donc, si nous voulons utiliser la norme TextAppearance attribut dans la coutume de visualiser et de lire ses valeurs dans le constructeur, on peut modifier le code de TextView de cette façon:
ColorStateList textColorApp = null;
int textSize = 15;
int typefaceIndex = -1;
int styleIndex = -1;
Resources.Theme theme = context.getTheme();
TypedArray a = theme.obtainStyledAttributes(attrs, R.styleable.CustomLabel, defStyle, 0);
TypedArray appearance = null;
int apResourceId = a.getResourceId(R.styleable.CustomLabel_android_textAppearance, -1);
a.recycle();
if (apResourceId != -1)
{
appearance =
theme.obtainStyledAttributes(apResourceId, new int[] { android.R.attr.textColor, android.R.attr.textSize,
android.R.attr.typeface, android.R.attr.textStyle });
}
if (appearance != null)
{
textColorApp = appearance.getColorStateList(0);
textSize = appearance.getDimensionPixelSize(1, textSize);
typefaceIndex = appearance.getInt(2, -1);
styleIndex = appearance.getInt(3, -1);
appearance.recycle();
}
Où CustomLabel est défini:
<declare-styleable name="CustomLabel">
<!-- Label text. -->
<attr name="android:text" />
<!-- Label text color. -->
<attr name="android:textColor" />
<!-- Combined text appearance properties. -->
<attr name="android:textAppearance" />
</declare-styleable>
Peut-être, je suis pris d'une certaine façon, mais Android documentation sur obtainStyledAttributes() est très pauvre.
L'extension de la norme composant de l'INTERFACE utilisateur
Dans le même temps, il nous suffit de prolonger la norme composant de l'INTERFACE utilisateur, à l'aide de tous ses déclarée attributs. Cette approche n'est pas si bon, parce que TextView par exemple, déclare un grand nombre de propriétés. Et il sera impossible pour mettre en œuvre toutes les fonctionnalités dans surchargée onMeasure() et onDraw().
Mais l'on peut sacrifier théorique large reusage de composant personnalisé. Dire "je sais exactement ce que les caractéristiques que je vais utiliser", et ne pas partager le code avec n'importe qui.
Ensuite, nous pouvons mettre en œuvre constructeur CustomComponent(Context, AttributeSet, defStyle)
.
Après l'appel de super(...)
nous aura tous les attributs analysées et disponibles par le biais des méthodes de lecture.
Il semble que Google a mis à jour sa page développeur et ajouté à différentes formations.
L'un d'eux porte sur la création de vues personnalisées et peuvent être trouvés ici
Mieux, Michael
Un grand merci pour la première réponse.
Quant à moi, j'avais juste un problème avec elle. Lors du gonflage de mon point de vue, j'ai eu un bug : java.lang.NoSuchMethodException : Mavue(Contexte, Les Attributs)
Je résolus par la création d'un nouveau constructeur :
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
// some code
}
Espérons que cela va aider !