Xamarin.Forms
Benutzerdefinierte Steuerelemente erstellen
Suche…
Einführung
Jede Xamarin.Forms
Ansicht hat einen begleitenden Renderer für jede Plattform, die eine Instanz eines systemeigenen Steuerelements erstellt. Wenn eine Ansicht auf einer bestimmten Plattform ViewRenderer
, wird die ViewRenderer
Klasse instanziiert.
Der Vorgang dafür ist wie folgt:
Erstellen Sie ein benutzerdefiniertes Xamarin.Forms-Steuerelement.
Verwenden Sie das benutzerdefinierte Steuerelement von Xamarin.Forms.
Erstellen Sie den benutzerdefinierten Renderer für das Steuerelement auf jeder Plattform.
Ein CheckBox-Steuerelement implementieren
In diesem Beispiel implementieren wir eine benutzerdefinierte Checkbox für Android und iOS.
Erstellen des benutzerdefinierten Steuerelements
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);
}
}
}
Wir beginnen mit dem Android Custom Renderer, indem wir eine neue Klasse ( CheckboxCustomRenderer
) im Android
Bereich unserer Lösung CheckboxCustomRenderer
.
Ein paar wichtige Details zu beachten:
- Wir brauchen die Spitze unserer Klasse mit dem ExportRenderer Attribute zu markieren , so dass der Renderer registriert ist
Xamarin.Forms
. Auf diese WeiseXamarin.Forms
wird diese Renderer verwenden , wenn es versucht , unser erstellenCheckbox
Objekt aufAndroid
. - Wir arbeiten
OnElementChanged
derOnElementChanged
Methode, bei der wir unserOnElementChanged
instanziieren und einrichten.
Verbrauch der benutzerdefinierten Steuerung
<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>
Erstellen des benutzerdefinierten Renderers auf jeder Plattform
Zum Erstellen der benutzerdefinierten Renderer-Klasse gehen Sie wie folgt vor:
- Erstellen Sie eine Unterklasse der
ViewRenderer<T1,T2>
KlasseViewRenderer<T1,T2>
, die das benutzerdefinierte Steuerelement darstellt. Das ersteCheckBox
sollte das benutzerdefinierte Steuerelement sein, für das der Renderer bestimmt ist, in diesem FallCheckBox
. Das zweite Typargument sollte das native Steuerelement sein, das das benutzerdefinierte Steuerelement implementiert. -
OnElementChanged
dieOnElementChanged
Methode, die die benutzerdefinierte Steuerungs- und Schreiblogik darstellt, um sie anzupassen. Diese Methode wird aufgerufen, wenn das entsprechendeXamarin.Forms
Steuerelement erstellt wird. - Fügen
ExportRenderer
der benutzerdefinierten Renderer-Klasse einExportRenderer
Attribut hinzu, um anzugeben, dass es zum Rendern des benutzerdefiniertenXamarin.Forms
Steuerelements verwendet wird. Dieses Attribut wird verwendet, um den benutzerdefinierten Renderer beiXamarin.Forms
zu registrieren.
Erstellen des benutzerdefinierten Renderers für 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;
}
}
}
}
Erstellen des benutzerdefinierten Renderers für iOS
Da in iOS das Kontrollkästchen nicht integriert ist, erstellen CheckBoxView
zunächst eine CheckBoxView
dann einen Renderer für unser Kontrollkästchen CheckBoxView
.
Die CheckBoxView
basiert auf zwei Bildern, nämlich checked_checkbox.png und unchecked_checkbox.png, sodass die Eigenschaft Color
ignoriert wird.
Die CheckBox-Ansicht:
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);
}
}
}
Der benutzerdefinierte CheckBox-Renderer:
[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;
}
}
}
}
Ergebnis: