Lors de la création d'applications complexes, vous souhaiterez souvent réutiliser le même groupe de vues à différents endroits de l'application. Une façon de résoudre ce problème consiste à créer une vue encapsulant la logique et la disposition d'un groupe de vues afin que vous puissiez les réutiliser sans dupliquer le code à différents endroits du projet. Dans ce didacticiel, vous apprendrez à utiliser des vues composées pour créer des vues personnalisées facilement réutilisables..
Sur Android, une vue composée d'un groupe de vues s'appelle une vue composée ou un composant composé. Dans ce didacticiel, vous allez créer un contrôle pour sélectionner une valeur dans une liste qui défile d'un côté à l'autre. Nous nommerons le composé spinner latéral car la vue par défaut du SDK Android permettant de choisir une valeur dans une liste s'appelle spinner. La capture d'écran suivante illustre ce que nous allons créer dans ce tutoriel..
Pour commencer, vous devez créer un nouveau projet Android avec Android 4.0 comme niveau de SDK minimum requis. Ce projet doit contenir uniquement une activité vide appelée Activité principale. le Activité
ne fait rien d'autre qu'initialiser la mise en page comme vous pouvez le voir dans l'extrait de code suivant.
Classe publique MainActivity étend Activity @Override protected void onCreate (Bundle savedInstanceState) super.onCreate (savedInstanceState); setContentView (R.layout.activity_main);
La mise en page pour Activité principale
est situé dans le /res/layout/activity_main.xml fichier et il ne devrait contenir qu'un vide Disposition relative
dans lequel la vue composée sera affichée plus tard.
Pour créer une vue composée, vous devez créer une nouvelle classe qui gère les vues dans la vue composée. Pour le côté spinner, vous avez besoin de deux Bouton
vues pour les flèches et un Affichage
voir pour afficher la valeur sélectionnée.
Pour commencer, créez le /res/layout/sidespinner_view.xml fichier de mise en page que nous allons utiliser pour la classe spinner côté, en veillant à envelopper les trois vues dans un
étiquette.
Ensuite, nous devons créer le SideSpinner
classe qui gonfle cette disposition et définit les flèches comme images d’arrière-plan pour les boutons. À ce stade, la vue composée ne fait rien car il n'y a rien à afficher pour le moment..
Classe publique SideSpinner étend LinearLayout private Button mPreviousButton; bouton privé mNextButton; public SideSpinner (contexte de contexte) super (contexte); initializeViews (contexte); public SideSpinner (contexte de contexte, AttributeSet attrs) super (contexte, attrs); initializeViews (contexte); public SideSpinner (contexte de contexte, AttributeSet attrs, int defStyle) super (contexte, attrs, defStyle); initializeViews (contexte); / ** * Gonfle les vues dans la disposition. * * @param context * le contexte actuel de la vue. * / private void initializeViews (contexte de contexte) LayoutInflater inflater = (LayoutInflater) contexte .getSystemService (Context.LAYOUT_INFLATER_SERVICE); inflater.inflate (R.layout.sidespinner_view, this); @Override protected void onFinishInflate () super.onFinishInflate (); // Définit les images pour les boutons précédent et suivant. Utilise // les images intégrées pour que vous n'ayez pas besoin d'ajouter d'images, mais dans // une application réelle, vos images doivent être dans le package // d'application afin qu'elles soient toujours disponibles. mPreviousButton = (Bouton) this .findViewById (R.id.sidespinner_view_previous); mPreviousButton .setBackgroundResource (android.R.drawable.ic_media_previous); mNextButton = (Bouton) this .findViewById (R.id.sidespinner_view_next); mNextButton .setBackgroundResource (android.R.drawable.ic_media_next);
Vous remarquerez que la vue composée étend la LinearLayout
groupe de vue. Cela signifie que toute disposition utilisant la vue composée a accès aux attributs de la disposition linéaire. En conséquence, la présentation de la vue composée est un peu différente de la normale, la balise racine est un
balise au lieu de la balise pour un groupe de vues comme
ou
.
Lorsque vous ajoutez la vue composée à la présentation de Activité principale
, l'étiquette pour la vue composée agira en tant que
étiquette. Une classe de vue composée peut dériver de toute classe dérivant de ViewGroup
, mais dans ce cas, la disposition linéaire est la plus appropriée car les vues sont disposées horizontalement.
A ce stade, le projet est compilé mais rien n’est visible car la vue composée n’est pas dans la présentation de Activité principale
. La vue spinner latérale doit être ajoutée à la présentation de l'activité comme toute autre vue. Le nom de la balise est le nom complet de la SideSpinner
classe, y compris l'espace de noms.
Ajouter le spinner latéral à Activité principale
, ajouter ce qui suit à la mise en page relative dans le /res/layout/activity_main.xml fichier.
Les attributs disponibles dans le
balise sont des attributs de la mise en page linéaire depuis le SideSpinner
la classe que nous avons créée étend la LinearLayout
classe. Si vous lancez le projet, le cône latéral doit être visible, mais il ne contient pas encore de valeurs..
Il manque encore quelques éléments si nous voulons réellement utiliser le cône latéral. Nous devrions pouvoir ajouter de nouvelles valeurs au cinéaste, sélectionner une valeur et obtenir la valeur sélectionnée.
Le moyen le plus simple d’ajouter de nouveaux comportements à une vue composée est d’ajouter de nouvelles méthodes publiques à la vue. SideSpinner
classe. Ces méthodes peuvent être utilisées par n’importe quel Activité
qui a une référence à la vue.
private CharSequence [] mSpinnerValues = null; private int mSelectedIndex = -1; / ** * Définit la liste de valeurs dans le compteur, en sélectionnant la première valeur * par défaut. * * @param values * les valeurs à définir dans le compteur. * / public void setValues (CharSequence [] values) mSpinnerValues = values; // Sélectionnez le premier élément du tableau de chaînes par défaut car // la liste de valeurs a été modifiée. setSelectedIndex (0); / ** * Définit l'index sélectionné du compteur. * * @param index * l'index de la valeur à sélectionner. * / public void setSelectedIndex (int index) // Si aucune valeur n'est définie pour le compteur, ne faites rien. if (mSpinnerValues == null || mSpinnerValues.length == 0) return; // Si la valeur d'index n'est pas valide, ne rien faire. si (index < 0 || index >= mSpinnerValues.length) return; // Définit l'index actuel et affiche la valeur. mSelectedIndex = index; TextView currentValue; currentValue = (TextView) this .findViewById (R.id.sidespinner_view_current_value); currentValue.setText (mSpinnerValues [index]); // Si la première valeur est affichée, cache le bouton précédent. if (mSelectedIndex == 0) mPreviousButton.setVisibility (INVISIBLE); else mPreviousButton.setVisibility (VISIBLE); // Si la dernière valeur est affichée, cache le bouton suivant. if (mSelectedIndex == mSpinnerValues.length - 1) mNextButton.setVisibility (INVISIBLE); else mNextButton.setVisibility (VISIBLE); / ** * Obtient la valeur sélectionnée du compteur ou null si aucun index * valide n'est encore défini. * * @retour la valeur sélectionnée du compteur. * / public CharSequence getSelectedValue () // Si aucune valeur n'est définie pour le compteur, retourne une chaîne vide. if (mSpinnerValues == null || mSpinnerValues.length == 0) return ""; // Si l'index actuel n'est pas valide, retourne une chaîne vide. si (mSelectedIndex < 0 || mSelectedIndex >= mSpinnerValues.length) return ""; return mSpinnerValues [mSelectedIndex]; / ** * Obtient l'index sélectionné du compteur. * * @retourne l'index sélectionné du compteur. * / public int getSelectedIndex () return mSelectedIndex;
le onFinishInflate
La méthode de la vue composée est appelée lorsque toutes les vues de la présentation sont gonflées et prêtes à être utilisées. C’est le lieu d’ajouter votre code si vous devez modifier des vues dans la vue composée..
Avec les méthodes que vous venez d’ajouter à la SideSpinner
classe, le comportement des boutons sélectionnant les valeurs précédente et suivante peut maintenant être ajouté. Remplacer le code existant dans le onFinishInflate
méthode avec ce qui suit:
@Override protected void onFinishInflate () // Lorsque les contrôles de la présentation sont en cours de gonflage, définissez // les rappels pour les flèches latérales. super.onFinishInflate (); // Lorsque vous appuyez sur le bouton précédent, sélectionnez la valeur // précédente dans la liste. mPreviousButton = (Bouton) this .findViewById (R.id.sidespinner_view_previous); mPreviousButton .setBackgroundResource (android.R.drawable.ic_media_previous); mPreviousButton.setOnClickListener (new OnClickListener () public void onClick (Afficher la vue) if (mSelectedIndex> 0) int newSelectedIndex = mSelectedIndex - 1; setSelectedIndex (newSelectedIndex);); // Lorsque l'utilisateur clique sur le bouton suivant, sélectionne l'élément suivant de la liste //. mNextButton = (Bouton) this .findViewById (R.id.sidespinner_view_next); mNextButton .setBackgroundResource (android.R.drawable.ic_media_next); mNextButton.setOnClickListener (new OnClickListener () public void onClick (vue d'affichage) if (mSpinnerValues! = null && mSelectedIndex < mSpinnerValues.length - 1) int newSelectedIndex = mSelectedIndex + 1; setSelectedIndex(newSelectedIndex); ); // Select the first value by default. setSelectedIndex(0);
Avec le nouveau créé setValues
et setSelectedIndex
méthodes, nous pouvons maintenant initialiser le spinner côté de notre code. Comme pour toute autre vue, vous devez trouver la vue latérale dans la présentation avec le findViewById
méthode. Nous pouvons ensuite appeler n'importe quelle méthode publique sur la vue à partir de l'objet renvoyé, y compris celles que nous venons de créer..
L’extrait de code suivant montre comment mettre à jour le onCreate
méthode du Activité principale
classe pour afficher une liste de valeurs dans la flèche latérale, en utilisant le setValues
méthode. Nous pouvons également sélectionner la deuxième valeur de la liste par défaut en appelant le setSelectedIndex
méthode.
Classe publique MainActivity étend Activity @Override protected void onCreate (Bundle savedInstanceState) super.onCreate (savedInstanceState); setContentView (R.layout.activity_main); // Initialise le spinner latéral à partir du code. SideSpinner fruitsSpinner; fruitsSpinner = (SideSpinner) this .findViewById (R.id.sidespinner_fruits); CharSequence fruitList [] = "Pomme", "Orange", "Poire", "Raisins"; fruitsSpinner.setValues (liste de fruits); fruitsSpinner.setSelectedIndex (1);
Si vous lancez l'application, le cône latéral doit fonctionner comme prévu. La liste des valeurs est affichée et la valeur Orange est sélectionné par défaut.
Les vues disponibles dans le SDK Android peuvent être modifiées via le code, mais certains attributs peuvent également être définis directement dans la présentation correspondante. Ajoutons un attribut à la roulette latérale qui définit les valeurs que cette dernière doit afficher..
Pour créer un attribut personnalisé pour la vue composée, nous devons d’abord définir cet attribut dans /res/values/attr.xml fichier. Chaque attribut de la vue composée doit être groupé dans un style avec un
étiquette. Pour le cône latéral, le nom de la classe est utilisé comme indiqué ci-dessous.
dans le
tag, le prénom
attribut contient l’identifiant utilisé pour faire référence au nouvel attribut dans la mise en page et le format
attribut contient le type du nouvel attribut.
Pour la liste de valeurs, le référence
type est utilisé car l'attribut fera référence à une liste de chaînes définies en tant que ressource. Les types de valeur normalement utilisés dans les modèles peuvent être utilisés pour vos attributs personnalisés, notamment booléen
, Couleur
, dimension
, enum
, entier
, flotte
et chaîne
.
Voici comment définir la ressource pour une liste de chaînes que le valeurs
attribut du côté spinner fera référence à. Il faut l'ajouter à la /res/values/strings.xml fichier comme indiqué ci-dessous.
- Concombre
- Patate
- Tomate
- Oignon
- Écraser
Pour tester le nouveau valeurs
attribuer, créer une vue latérale spinner dans la Activité principale
disposition ci-dessous le spinner côté existant. L’attribut doit être préfixé par un espace de nom ajouté à la Disposition relative
, tel que xmlns: sidespinner = "http://schemas.android.com/apk/res-auto"
. C'est ce que la mise en page finale /res/layout/activity_main.xml devrait ressembler.
Finalement, le SideSpinner
la classe doit être modifiée pour lire le valeurs
attribut. La valeur de chaque attribut de la vue est disponible dans le AttributeSet
objet qui est passé en tant que paramètre du constructeur de la vue.
Pour obtenir la valeur de votre coutume valeurs
attribut, nous appelons d’abord le obtenirStyledAttributes
méthode du AttributeSet
objet avec le nom du styleable contenant l'attribut. Ceci retourne la liste des attributs pour ce stylable en tant que TypedArray
objet.
Nous appelons ensuite la méthode getter du TypedArray
objet qui a le bon type pour l'attribut souhaité, en passant l'identificateur de l'attribut en tant que paramètre. Le bloc de code suivant montre comment modifier le constructeur du spinner latéral pour obtenir la liste des valeurs et les définir dans le spinner latéral.
public SideSpinner (contexte de contexte) super (contexte); initializeViews (contexte); public SideSpinner (contexte de contexte, AttributeSet attrs) super (contexte, attrs); TypedArray typedArray; typedArray = contexte .obtainStyledAttributes (attrs, R.styleable.SideSpinner); mSpinnerValues = typedArray .getTextArray (R.styleable.SideSpinner_values); typedArray.recycle (); initializeViews (contexte); public SideSpinner (contexte de contexte, AttributeSet attrs, int defStyle) super (contexte, attrs, defStyle); TypedArray typedArray; typedArray = contexte .obtainStyledAttributes (attrs, R.styleable.SideSpinner); mSpinnerValues = typedArray .getTextArray (R.styleable.SideSpinner_values); typedArray.recycle (); initializeViews (contexte);
Si vous lancez l'application, vous devriez voir deux fileuses latérales qui fonctionnent indépendamment l'une de l'autre..
La dernière étape que nous devons terminer consiste à enregistrer et à restaurer l'état de la vue composée. Lorsqu'une activité est détruite et recréée, par exemple lors de la rotation du périphérique, les valeurs des vues natives avec un identificateur unique sont automatiquement enregistrées et restaurées. Ce n'est actuellement pas vrai pour le côté spinner.
L'état des vues n'est pas enregistré. Les identifiants des vues dans la SideSpinner
Les classes ne sont pas uniques car elles peuvent être réutilisées plusieurs fois. Cela signifie que nous sommes responsables de la sauvegarde et de la restauration des valeurs des vues dans la vue composée. Nous faisons cela en mettant en œuvre le onSaveInstanceState
, onRestoreInstanceState
, et dispatchSaveInstanceState
méthodes. Le bloc de code suivant montre comment procéder pour le spinner latéral.
/ ** * Identifiant de l'état dans lequel enregistrer l'index * sélectionné du cône latéral. * / private static String STATE_SELECTED_INDEX = "SelectedIndex"; / ** * Identifiant de l'état de la super classe. * / private static String STATE_SUPER_CLASS = "SuperClass"; @Override protected Parcelable onSaveInstanceState () Bundle bundle = new Bundle (); bundle.putParcelable (STATE_SUPER_CLASS, super.onSaveInstanceState ()); bundle.putInt (STATE_SELECTED_INDEX, mSelectedIndex); retourner le paquet; @Override protected void onRestoreInstanceState (état parcellisable) if (état de l'instance du groupe) Bundle bundle = (groupe) de l'état; super.onRestoreInstanceState (bundle .getParcelable (STATE_SUPER_CLASS)); setSelectedIndex (bundle.getInt (STATE_SELECTED_INDEX)); else super.onRestoreInstanceState (état); @Override protected void dispatchSaveInstanceState (SparseArraycontainer) // Vérifie que l'état des vues enfants du côté // spinner n'est pas enregistré car nous gérons l'état dans // onSaveInstanceState. super.dispatchFreezeSelfOnly (conteneur); @Override protected void dispatchRestoreInstanceState (SparseArray container) // Vérifie que l'état des vues enfant du côté // spinner n'est pas restauré car nous gérons l'état dans // onSaveInstanceState. super.dispatchThawSelfOnly (conteneur);
Le cône latéral est maintenant terminé. Les deux fileuses fonctionnent comme prévu et leurs valeurs sont restaurées si l'activité est détruite et recréée. Vous pouvez maintenant appliquer ce que vous avez appris pour réutiliser un groupe de vues dans une application Android à l'aide de vues composées..