Xamarin.Forms
Création de contrôles personnalisés
Recherche…
Introduction
Chaque vue Xamarin.Forms est accompagnée d'un rendu pour chaque plate-forme qui crée une instance d'un contrôle natif. Lorsqu'une vue est rendue sur la plate-forme spécifique, la classe ViewRenderer est instanciée.
Le processus pour ce faire est le suivant:
Créez un contrôle personnalisé Xamarin.Forms.
Consommez le contrôle personnalisé de Xamarin.Forms.
Créez le moteur de rendu personnalisé pour le contrôle sur chaque plate-forme.
Implémenter un contrôle CheckBox
Dans cet exemple, nous allons implémenter une case à cocher personnalisée pour Android et iOS.
Création du contrôle personnalisé
namespace CheckBoxCustomRendererExample
{
public class Checkbox : View
{
public static readonly BindableProperty IsCheckedProperty = BindableProperty.Create<Checkbox, bool>(p => p.IsChecked, true, propertyChanged: (s, o, n) => { (s as Checkbox).OnChecked(new EventArgs()); });
public static readonly BindableProperty ColorProperty = BindableProperty.Create<Checkbox, Color>(p => p.Color, Color.Default);
public bool IsChecked
{
get
{
return (bool)GetValue(IsCheckedProperty);
}
set
{
SetValue(IsCheckedProperty, value);
}
}
public Color Color
{
get
{
return (Color)GetValue(ColorProperty);
}
set
{
SetValue(ColorProperty, value);
}
}
public event EventHandler Checked;
protected virtual void OnChecked(EventArgs e)
{
if (Checked != null)
Checked(this, e);
}
}
}
Nous commencerons par le moteur de rendu personnalisé Android en créant une nouvelle classe ( CheckboxCustomRenderer ) dans la partie Android de notre solution.
Quelques détails importants à noter:
- Nous devons marquer le haut de notre classe avec l'attribut ExportRenderer pour que le rendu soit enregistré avec
Xamarin.Forms. De cette façon,Xamarin.Formsutilisera ce moteur de rendu lorsqu'ilXamarin.Formsde créer notre objetCheckboxsurAndroid. - Nous faisons la plupart de notre travail dans la méthode
OnElementChanged, où nous instancions et configurons notre contrôle natif.
Consommer le contrôle personnalisé
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:CheckBoxCustomRendererExample" x:Class="CheckBoxCustomRendererExample.CheckBoxCustomRendererExamplePage">
<StackLayout Padding="20">
<local:Checkbox Color="Aqua" />
</StackLayout>
</ContentPage>
Création du moteur de rendu personnalisé sur chaque plate-forme
Le processus de création de la classe de rendu personnalisé est le suivant:
- Créez une sous-classe de la classe
ViewRenderer<T1,T2>qui affiche le contrôle personnalisé. Le premier argument de type doit être le contrôle personnalisé utilisé par le moteur de rendu, dans ce cas,CheckBox. Le deuxième argument de type doit être le contrôle natif qui implémentera le contrôle personnalisé. - Remplacez la méthode
OnElementChangedquiOnElementChangedle contrôle personnalisé et écrit la logique pour le personnaliser. Cette méthode est appelée lorsque le contrôleXamarin.Formscorrespondant est créé. - Ajoutez un attribut
ExportRendererà la classe de rendu personnalisée pour indiquer qu'elle sera utilisée pour effectuer le rendu du contrôle personnaliséXamarin.Forms. Cet attribut est utilisé pour enregistrer le moteur de rendu personnalisé avecXamarin.Forms.
Création du moteur de rendu personnalisé pour Android
[assembly: ExportRenderer(typeof(Checkbox), typeof(CheckBoxRenderer))]
namespace CheckBoxCustomRendererExample.Droid
{
public class CheckBoxRenderer : ViewRenderer<Checkbox, CheckBox>
{
private CheckBox checkBox;
protected override void OnElementChanged(ElementChangedEventArgs<Checkbox> e)
{
base.OnElementChanged(e);
var model = e.NewElement;
checkBox = new CheckBox(Context);
checkBox.Tag = this;
CheckboxPropertyChanged(model, null);
checkBox.SetOnClickListener(new ClickListener(model));
SetNativeControl(checkBox);
}
private void CheckboxPropertyChanged(Checkbox model, String propertyName)
{
if (propertyName == null || Checkbox.IsCheckedProperty.PropertyName == propertyName)
{
checkBox.Checked = model.IsChecked;
}
if (propertyName == null || Checkbox.ColorProperty.PropertyName == propertyName)
{
int[][] states = {
new int[] { Android.Resource.Attribute.StateEnabled}, // enabled
new int[] {Android.Resource.Attribute.StateEnabled}, // disabled
new int[] {Android.Resource.Attribute.StateChecked}, // unchecked
new int[] { Android.Resource.Attribute.StatePressed} // pressed
};
var checkBoxColor = (int)model.Color.ToAndroid();
int[] colors = {
checkBoxColor,
checkBoxColor,
checkBoxColor,
checkBoxColor
};
var myList = new Android.Content.Res.ColorStateList(states, colors);
checkBox.ButtonTintList = myList;
}
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (checkBox != null)
{
base.OnElementPropertyChanged(sender, e);
CheckboxPropertyChanged((Checkbox)sender, e.PropertyName);
}
}
public class ClickListener : Java.Lang.Object, IOnClickListener
{
private Checkbox _myCheckbox;
public ClickListener(Checkbox myCheckbox)
{
this._myCheckbox = myCheckbox;
}
public void OnClick(global::Android.Views.View v)
{
_myCheckbox.IsChecked = !_myCheckbox.IsChecked;
}
}
}
}
Création du moteur de rendu personnalisé pour iOS
Comme dans iOS, la case à cocher n'est pas intégrée, nous allons d'abord créer un CheckBoxView puis créer un moteur de rendu pour notre case à cocher Xamarin.Forms.
Le CheckBoxView est basé sur deux images, checked_checkbox.png et unchecked_checkbox.png, afin que la propriété Color soit ignorée.
La vue CheckBox:
namespace CheckBoxCustomRendererExample.iOS
{
[Register("CheckBoxView")]
public class CheckBoxView : UIButton
{
public CheckBoxView()
{
Initialize();
}
public CheckBoxView(CGRect bounds)
: base(bounds)
{
Initialize();
}
public string CheckedTitle
{
set
{
SetTitle(value, UIControlState.Selected);
}
}
public string UncheckedTitle
{
set
{
SetTitle(value, UIControlState.Normal);
}
}
public bool Checked
{
set { Selected = value; }
get { return Selected; }
}
void Initialize()
{
ApplyStyle();
TouchUpInside += (sender, args) => Selected = !Selected;
// set default color, because type is not UIButtonType.System
SetTitleColor(UIColor.DarkTextColor, UIControlState.Normal);
SetTitleColor(UIColor.DarkTextColor, UIControlState.Selected);
}
void ApplyStyle()
{
SetImage(UIImage.FromBundle("Images/checked_checkbox.png"), UIControlState.Selected);
SetImage(UIImage.FromBundle("Images/unchecked_checkbox.png"), UIControlState.Normal);
}
}
}
Le moteur de rendu personnalisé CheckBox:
[assembly: ExportRenderer(typeof(Checkbox), typeof(CheckBoxRenderer))]
namespace CheckBoxCustomRendererExample.iOS
{
public class CheckBoxRenderer : ViewRenderer<Checkbox, CheckBoxView>
{
/// <summary>
/// Handles the Element Changed event
/// </summary>
/// <param name="e">The e.</param>
protected override void OnElementChanged(ElementChangedEventArgs<Checkbox> e)
{
base.OnElementChanged(e);
if (Element == null)
return;
BackgroundColor = Element.BackgroundColor.ToUIColor();
if (e.NewElement != null)
{
if (Control == null)
{
var checkBox = new CheckBoxView(Bounds);
checkBox.TouchUpInside += (s, args) => Element.IsChecked = Control.Checked;
SetNativeControl(checkBox);
}
Control.Checked = e.NewElement.IsChecked;
}
Control.Frame = Frame;
Control.Bounds = Bounds;
}
/// <summary>
/// Handles the <see cref="E:ElementPropertyChanged" /> event.
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The <see cref="PropertyChangedEventArgs"/> instance containing the event data.</param>
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName.Equals("Checked"))
{
Control.Checked = Element.IsChecked;
}
}
}
}
Résultat:

