Xamarin.Forms
Aangepaste besturingselementen maken
Zoeken…
Invoering
Elke Xamarin.Forms
weergave heeft een bijbehorende renderer voor elk platform dat een instantie van een native besturingselement maakt. Wanneer een weergave wordt weergegeven op het specifieke platform, wordt de ViewRenderer
klasse geïnstantieerd.
Het proces hiervoor is als volgt:
Maak een Xamarin.Forms aangepast besturingselement.
Gebruik de aangepaste besturing van Xamarin.Forms.
Maak de aangepaste renderer voor de besturing op elk platform.
Een CheckBox-besturingselement implementeren
In dit voorbeeld implementeren we een aangepaste checkbox voor Android en iOS.
Aangepast besturingselement maken
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);
}
}
}
We beginnen met de Android Custom Renderer door een nieuwe klasse ( CheckboxCustomRenderer
) te maken in het Android
gedeelte van onze oplossing.
Een paar belangrijke details om op te merken:
- We moeten de top van onze klasse markeren met het kenmerk ExportRenderer zodat de renderer wordt geregistreerd bij
Xamarin.Forms
. Op deze manier zalXamarin.Forms
deze renderer gebruiken wanneer het probeert onsCheckbox
object opAndroid
. - We doen het grootste deel van ons werk in de
OnElementChanged
methode, waarbij we onze eigen besturing instantiëren en instellen.
De aangepaste bediening gebruiken
<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>
De aangepaste renderer maken op elk platform
Het proces voor het maken van de aangepaste rendererklasse is als volgt:
- Maak een subklasse van de
ViewRenderer<T1,T2>
die het aangepaste besturingselementViewRenderer<T1,T2>
. Het eerste type argument moet het aangepaste besturingselement zijn waarvoor de renderer is bedoeld, in dit gevalCheckBox
. Het tweede type argument moet het native besturingselement zijn dat het aangepaste besturingselement implementeert. - Overschrijf de
OnElementChanged
methode die de aangepaste besturing enOnElementChanged
om deze aan te passen. Deze methode wordt aangeroepen wanneer het bijbehorendeXamarin.Forms
besturingselement wordt gemaakt. - Voeg een
ExportRenderer
kenmerk toe aan de aangepaste rendererklasse om op te geven dat dit wordt gebruikt om het aangepaste besturingselementXamarin.Forms
te renderen. Dit kenmerk wordt gebruikt om de aangepaste renderer te registreren bijXamarin.Forms
.
De aangepaste Renderer voor Android maken
[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;
}
}
}
}
De aangepaste Renderer voor iOS maken
Aangezien in iOS het ingebouwde selectievakje niet is ingebouwd, maken we eerst een CheckBoxView
en maken we vervolgens een renderer voor ons Xamarin.Forms-selectievakje.
De CheckBoxView
is gebaseerd op twee afbeeldingen, check_checkbox.png en unchecked_checkbox.png, zodat de eigenschap Color
wordt genegeerd.
De weergave 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);
}
}
}
De aangepaste renderer van 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;
}
}
}
}
Resultaat: