Xamarin.Forms
Creazione di controlli personalizzati
Ricerca…
introduzione
Ogni vista Xamarin.Forms
ha un renderer di accompagnamento per ogni piattaforma che crea un'istanza di un controllo nativo. Quando una vista viene renderizzata sulla piattaforma specifica, la classe ViewRenderer
viene istanziata.
Il processo per farlo è il seguente:
Creare un controllo personalizzato Xamarin.Forms.
Consuma il controllo personalizzato da Xamarin.Forms.
Creare il renderizzatore personalizzato per il controllo su ciascuna piattaforma.
Implementazione di un controllo CheckBox
In questo esempio implementeremo una casella di controllo personalizzata per Android e iOS.
Creazione del controllo personalizzato
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);
}
}
}
Iniziamo con il rendering personalizzato di Android creando una nuova classe ( CheckboxCustomRenderer
) nella parte Android
della nostra soluzione.
Alcuni dettagli importanti da notare:
- Dobbiamo contrassegnare la parte superiore della nostra classe con l'attributo ExportRenderer in modo che il renderer sia registrato con
Xamarin.Forms
. In questo modo,Xamarin.Forms
utilizzerà questo renderer quando sta tentando di creare il nostro oggettoCheckbox
suAndroid
. - Stiamo facendo la maggior parte del nostro lavoro nel metodo
OnElementChanged
, dove istanziamo e impostiamo il nostro controllo nativo.
Consumare il controllo personalizzato
<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>
Creazione del renderizzatore personalizzato su ciascuna piattaforma
La procedura per la creazione della classe di rendering personalizzata è la seguente:
- Creare una sottoclasse della classe
ViewRenderer<T1,T2>
che esegue il rendering del controllo personalizzato. Il primo argomento di tipo dovrebbe essere il controllo personalizzato per il renderer, in questo casoCheckBox
. Il secondo argomento di tipo dovrebbe essere il controllo nativo che implementerà il controllo personalizzato. - Sovrascrivi il metodo
OnElementChanged
cheOnElementChanged
rendering del controllo personalizzato e della logica di scrittura per personalizzarlo. Questo metodo viene chiamato quando viene creato il controlloXamarin.Forms
corrispondente. - Aggiungi un attributo
ExportRenderer
alla classe di rendering personalizzata per specificare che verrà utilizzato per il rendering del controllo personalizzatoXamarin.Forms
. Questo attributo viene utilizzato per registrare il renderizzatore personalizzato conXamarin.Forms
.
Creazione del renderizzatore personalizzato per 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;
}
}
}
}
Creazione del renderizzatore personalizzato per iOS
Poiché in iOS la casella di controllo non è integrata, creeremo prima un CheckBoxView
e poi creeremo un renderer per la nostra casella di controllo Xamarin.Forms.
CheckBoxView
è basato su due immagini: checked_checkbox.png e unchecked_checkbox.png, quindi la proprietà Color
verrà ignorata.
La vista 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);
}
}
}
Il renderer personalizzato 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;
}
}
}
}
Risultato: