Xamarin.Forms
Skapa anpassade kontroller
Sök…
Introduktion
Varje Xamarin.Forms
vy har en åtföljande återgivare för varje plattform som skapar en instans av en egen kontroll. När en vy återges på den specifika plattformen ViewRenderer
klassen.
Processen för att göra detta är följande:
Skapa en Xamarin.Forms anpassad kontroll.
Konsumera den anpassade kontrollen från Xamarin.Forms.
Skapa den anpassade renderaren för kontrollen på varje plattform.
Implementera en CheckBox-kontroll
I det här exemplet kommer vi att implementera en anpassad checkbox för Android och iOS.
Skapa den anpassade kontrollen
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);
}
}
}
Vi börjar med Android Custom Renderer genom att skapa en ny klass ( CheckboxCustomRenderer
) i Android
delen av vår lösning.
Några viktiga detaljer att notera:
- Vi måste markera toppen av vår klass med attributet ExportRenderer så att renderaren är registrerad hos
Xamarin.Forms
. På detta sätt kommerXamarin.Forms
att använda den här renderaren när den försöker skapa vårtCheckbox
objekt påAndroid
. - Vi gör det mesta av vårt arbete med
OnElementChanged
metoden, där vi initierar och ställer in vår egen kontroll.
Konsumerar den anpassade kontrollen
<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>
Skapa den anpassade återgivaren på varje plattform
Processen för att skapa den anpassade återgivarklassen är enligt följande:
- Skapa en underklass i klassen
ViewRenderer<T1,T2>
som gör den anpassade kontrollen. Det första typargumentet bör vara den anpassade kontrollen som renderaren är för, i detta fallCheckBox
. Det andra typargumentet bör vara den ursprungliga kontrollen som kommer att implementera den anpassade kontrollen. - Överstyr metoden
OnElementChanged
som gör den anpassade kontrollen och skrivlogiken för att anpassa den. Den här metoden kallas när motsvarandeXamarin.Forms
kontroll skapas. - Lägg till ett
ExportRenderer
attribut till den anpassade återgivarklassen för att ange att det ska användas för att göraXamarin.Forms
anpassad kontroll. Detta attribut används för att registrera den anpassade renderaren medXamarin.Forms
.
Skapa den anpassade återgivaren 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;
}
}
}
}
Skapa den anpassade återgivaren för iOS
Eftersom det i iOS inte är en inbyggd kryssruta kommer vi att skapa en CheckBoxView
först och sedan skapa en renderer för vår Xamarin.Forms-kryssruta.
CheckBoxView
är baserat på två bilder check_checkbox.png och unchecked_checkbox.png så att egenskapen Color
ignoreras.
CheckBox-vyn:
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);
}
}
}
CheckBox anpassad återgivare:
[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;
}
}
}
}
Resultat: