Loupe

Créer un contrôle personnalisé avec Xamarin Android

Si vous êtes développeur .NET, vous avez déjà été confronté au besoin de disposer d'un contrôle personnalisé qui vous permet de disposer de fonctionnalités supplémentaires ou différentes, en fonction des besoins.

Sur Xamarin Android (et même sur iOS), cette fonctionnalité est toujours présente: vous pouvez continuer à créer vos propres contrôles mais il y a quelques particularités qu'il faut connaitre pour ne pas avoir de petite surprises.

Comme pour un développement .NET classique, la première étape est d'hériter d'une classe de base qui correspond à la fonctionnalité que vous voulez étendre/modifier:

public class CustomSpinner : MvxAppCompatSpinner
{
        
}

Comme pour la majorité des contrôles Android, il est nécessaire de disposer d'un (ou plusieurs) constructeur(s) permettant d'initialiser le contexte et d'autres attributs:

Base.png

Le code de notre contrôle se transforme donc en ceci:

public class CustomSpinner : MvxAppCompatSpinner
{
    public CustomSpinner(Context context, IAttributeSet attrs) : base(context, attrs)
    {
    }

    public CustomSpinner(Context context, IAttributeSet attrs, IMvxAdapter adapter) : base(context, attrs, adapter)
    {
    }

    public CustomSpinner(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer)
    {
    }
}

Dès lors, vous pouvez utiliser votre nouveau contrôle directement dans votre vue, de la même façon que n'importe quel contrôle:

 <CustomSpinner
android:id="@+id/DocumentAskForTaskPopup_SubSubjectSpinner"
android:layout_marginLeft="2dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:spinnerMode="dialog"
android:paddingBottom="4dp"
android:paddingTop="4dp" />

Le principe même de créer un contrôle personnalisé est de venir rajouter des comportements ou des fonctionnalités à un contrôle existant. Cela passe le plus souvent par l'utilisation de propriétés supplémentaires:

public class CustomSpinner : MvxAppCompatSpinner
{
    public string HintText { get; set; }

    public Color HintColor { get; set; }

    public CustomSpinner(Context context, IAttributeSet attrs) : base(context, attrs)
    {
    }

    public CustomSpinner(Context context, IAttributeSet attrs, IMvxAdapter adapter) : base(context, attrs, adapter)
    {
    }

    public CustomSpinner(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer)
    {
    }
}

En modifiant alors notre vue pour affecter des valeurs aux propriétés, on se retrouve avec ce code, qui affecte bien une couleur à la propriété HintColor:

<CustomSpinner
android:id="@+id/DocumentAskForTaskPopup_SubSubjectSpinner"
android:layout_marginLeft="2dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:spinnerMode="dialog"
local:HintColor="#808080"
android:paddingBottom="4dp"
android:paddingTop="4dp" />

A l'exécution, on constate le résultat suivant:

 Results.png

Quoi ?! Mon ARGB vaut 0, 0, 0 et 0 ? Alors que j'ai bien indiqué la valeur #808080 dans ma vue ? Comment est-ce possible ?!

La raison vient du fait que vous avez affecté une valeur dans la vue mais vous devez indiquer au système comment faire le lien entre la vue et le code du contrôle. Pour cela, vous devez créer un fichier XML (placé dans le répertoire values) dans lequel vous indiquez, pour votre contrôle, le nom et le type des propriétés:

<?xml version="1.0" encoding="utf-8"?>
<resources>
  <declare-styleable name="CustomSpinner">
    <attr name="HintText" format="string"/>
    <attr name="HintColor" format="color"/>
  </declare-styleable>
</resources>

Ensuite, il vous faut faire en sorte d'affecter les valeurs de la vue aux propriétés du contrôle, et cela passe par une modification du constructeur de votre contrôle pour lui indiquer comment faire cette liaison:

public CustomSpinner(Context context, IAttributeSet attrs) : base(context, attrs)
{
    using (var styledAttributes = context.ObtainStyledAttributes(attrs, Resource.Styleable.CustomSpinner))
    {
        this.HintText = styledAttributes.GetText(Resource.Styleable.CustomSpinner_HintText);
        this.HintColor = styledAttributes.GetColor(Resource.Styleable.CustomSpinner_HintColor, Color.Black);
    }
}

Et voilà, si vous exécutez à nouveau votre application, vous pourrez constater que votre/vos propriétés sont bien initialisées à partir des valeurs saisies dans la vue:

Results2.png

Au final, le développement de contrôles personnalisés est assez simple, avec Xamarin Android: il faut juste faire attention à 2/3 petites choses!

 

Happy coding!

 

Ces billets pourraient aussi vous intéresser

Vous nous direz ?!

Commentaires

comments powered by Disqus