我有一个 xamarin 自定义选择器渲染器,其中有下拉箭头,我试图将其转换为 MAUI 中的处理程序。我已经成功转换了 Android 版本,但我对 iOS 版本一无所知。这里有什么建议吗?
xamarin 渲染器:
public class CustomPickerRenderer : PickerRenderer
{
public CustomPicker ElementV2 => Element as CustomPicker;
public UITextFieldPadding ControlV2 => Control as UITextFieldPadding;
private static string _defaultDownArrow = "\uf0d7";
protected override UITextField CreateNativeControl()
{
var control = new UITextFieldPadding(RectangleF.Empty)
{
Padding = ElementV2.Padding,
BorderStyle = UITextBorderStyle.RoundedRect,
ClipsToBounds = true
};
UpdateBackground(control);
return control;
}
protected void UpdateBackground(UITextField control)
{
if (control == null) return;
control.Layer.CornerRadius = ElementV2.CornerRadius;
control.Layer.BorderWidth = ElementV2.BorderThickness;
control.Layer.BorderColor = ElementV2.BorderColor.ToCGColor();
var arrowTextSymbol = !string.IsNullOrWhiteSpace(ElementV2.IconGlyph) ? ElementV2.IconGlyph : _defaultDownArrow;
var downArrow = new UILabel
{
Text = $"{arrowTextSymbol} " ,
TextColor = ElementV2.IconColor.ToUIColor(),
Font = UIFont.FromName(ElementV2.IconFontFamily, (float)ElementV2.IconSize),
TextAlignment = UITextAlignment.Center
};
control.RightView = downArrow;
control.RightViewMode = UITextFieldViewMode.Always;
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == CustomPicker.PaddingProperty.PropertyName)
{
UpdatePadding();
}
if (e.PropertyName == CustomPicker.BorderColorProperty.PropertyName)
{
UpdateBorderColor();
}
if (e.PropertyName == CustomPicker.IconGlyphProperty.PropertyName)
{
UpdateIcon();
}
base.OnElementPropertyChanged(sender, e);
}
protected void UpdateBorderColor()
{
if (Control == null)
return;
ControlV2.Layer.BorderColor = ElementV2.BorderColor.ToCGColor();
}
protected void UpdatePadding()
{
if (Control == null)
return;
ControlV2.Padding = ElementV2.Padding;
}
protected void UpdateIcon()
{
if (Control == null)
return;
var arrowTextSymbol = !string.IsNullOrWhiteSpace(ElementV2.IconGlyph) ? ElementV2.IconGlyph : _defaultDownArrow;
var downArrow = new UILabel
{
Text = $"{arrowTextSymbol} ",
TextColor = ElementV2.IconColor.ToUIColor(),
Font = UIFont.FromName(ElementV2.IconFontFamily, (float)ElementV2.IconSize)
};
ControlV2.RightView = downArrow;
ControlV2.RightViewMode = UITextFieldViewMode.Always;
ControlV2.LeftView = new UIView(new CGRect(0, 0, 10, 0));
ControlV2.LeftViewMode = UITextFieldViewMode.Always;
ControlV2.Padding = ElementV2.Padding;
}
}
带填充的文本字段:
public class UITextFieldPadding : UITextField
{
private Thickness _padding = new Thickness(5);
public Thickness Padding
{
get => _padding;
set
{
if (_padding != value)
{
_padding = value;
//InvalidateIntrinsicContentSize();
}
}
}
public UITextFieldPadding()
{
}
public UITextFieldPadding(NSCoder coder) : base(coder)
{
}
public UITextFieldPadding(CGRect rect) : base(rect)
{
}
public override CGRect TextRect(CGRect forBounds)
{
var insets = new UIEdgeInsets((float)Padding.Top, (float)Padding.Left, (float)Padding.Bottom, (float)Padding.Right);
return insets.InsetRect(forBounds);
}
public override CGRect PlaceholderRect(CGRect forBounds)
{
var insets = new UIEdgeInsets((float)Padding.Top, (float)Padding.Left, (float)Padding.Bottom, (float)Padding.Right);
return insets.InsetRect(forBounds);
}
public override CGRect EditingRect(CGRect forBounds)
{
var insets = new UIEdgeInsets((float)Padding.Top, (float)Padding.Left, (float)Padding.Bottom, (float)Padding.Right);
return insets.InsetRect(forBounds);
}
}
这是使用映射创建处理程序的一种方法。我希望这就是您正在寻找的。这不是生产就绪的代码,只是为了让您可以找到自己的方法并使其成为您自己的代码。
我们从一个 Picker 类开始,我们可以使用它从 xaml 文件或后面的代码访问 Padding 和 BorderColor。
public class PickerRowEx : Picker
{
public static readonly BindableProperty PaddingProperty = BindableProperty.Create(nameof(Padding), typeof(Thickness), typeof(PickerRowEx),new Thickness(0));
public Thickness Padding
{
get => (Thickness)GetValue(PaddingProperty);
set => SetValue(PaddingProperty, value);
}
public static readonly BindableProperty BorderColorProperty = BindableProperty.Create(nameof(BorderColor), typeof(Color), typeof(PickerRowEx));
public Color BorderColor
{
get => (Color)GetValue(BorderColorProperty);
set => SetValue(BorderColorProperty, value);
}
}
在此之后,我们使用 partial
进行一些
多文件。从标准开始 这是所有其他平台所共有的,我们在这里有我们的映射,如果你愿意的话,我们的起点。
PickerRowExHandler.cs
在这里我们看到与您的 UpdateValue
类似的
OnElementPropertyChanged
using Microsoft.Maui.Handlers;
public partial class PickerRowExHandler
{
public static new PropertyMapper<IPicker, PickerHandler> Mapper = new PropertyMapper<IPicker, PickerHandler>(PickerHandler.Mapper)
{
["Padding"] = MapPadding,
["BorderColor"] = MapBorderColor,
};
public PickerRowExHandler() : base(Mapper)
{
}
public PickerRowExHandler(PropertyMapper mapper) : base(mapper)
{
}
public override void UpdateValue(string propertyName)
{
base.UpdateValue(propertyName);
if (propertyName == PickerRowEx.PaddingProperty.PropertyName)
{
if(VirtualView is PickerRowEx pickerRowEx)
{
SetPadding(pickerRowEx.Padding);
}
}
if (propertyName == PickerRowEx.BorderColorProperty.PropertyName)
{
if (VirtualView is PickerRowEx pickerRowEx)
{
SetBorderColor(pickerRowEx.BorderColor);
}
}
}
public static void MapPadding(PickerHandler handler, IPicker picker)
{
if (handler is PickerRowExHandler pickerHandler && pickerHandler.VirtualView is PickerRowEx pickerRowEx)
{
pickerHandler.SetPadding(pickerRowEx.Padding);
}
}
public static void MapBorderColor(PickerHandler handler, IPicker picker)
{
if (handler is PickerRowExHandler pickerHandler && pickerHandler.VirtualView is PickerRowEx pickerRowEx)
{
pickerHandler.SetBorderColor(pickerRowEx.BorderColor);
}
}
}
之后我们制作平台特定的文件。
PickerRowExHandler.iOS.cs
。您需要为您想要使用的每个平台制作其中一个。
using UIKit;
public partial class PickerRowExHandler : PickerHandler
{
public void SetPadding(Thickness padding)
{
var margin = 5;
if (PlatformView is not UITextField textField) return;
textField.LeftView = new UIView(new CGRect(0, 0, padding.Left, textField.Frame.Height));
textField.LeftViewMode = UITextFieldViewMode.Always;
var fontAwesomeLabel = new UILabel
{
Text = "\uf0d7",
Font = UIFont.FromName("Font Awesome 5 Free", 20),
TextAlignment = UITextAlignment.Left,
};
fontAwesomeLabel.SizeToFit();
var originalLabelWidth = fontAwesomeLabel.Frame.Width + margin;
var newContainerWidth = originalLabelWidth + (float)padding.Right;
var labelYPosition = (textField.Frame.Height - fontAwesomeLabel.Frame.Height) / 2;
var containerView = new UIView(new CGRect(0, 0, newContainerWidth, textField.Frame.Height));
fontAwesomeLabel.Frame = new CGRect((float)padding.Right, labelYPosition, originalLabelWidth, fontAwesomeLabel.Frame.Height);
containerView.AddSubview(fontAwesomeLabel);
textField.RightView = containerView;
textField.RightViewMode = UITextFieldViewMode.Always;
}
public void SetBorderColor(Color color)
{
PlatformView.Layer.CornerRadius = 10;
PlatformView.Layer.BorderWidth = 1;
PlatformView.Layer.BorderColor = color.ToCGColor();
}
}
使用前不要忘记在您的
MauiProgram.cs
中注册此控件。
<VerticalStackLayout
HorizontalOptions="Center"
Spacing="20"
VerticalOptions="Center">
<controls:PickerRowEx
x:Name="MyPicker"
Title="Pick an Item"
Margin="10"
Padding="0,0,0,0"
BackgroundColor="Transparent"
BorderColor="DarkBlue"
HorizontalOptions="CenterAndExpand"
HorizontalTextAlignment="Center"
MinimumWidthRequest="200"
SelectedIndexChanged="MyPicker_SelectedIndexChanged"
TextColor="Blue">
<controls:PickerRowEx.Items>
<x:String>Green</x:String>
<x:String>Purple</x:String>
<x:String>Blue</x:String>
<x:String>Yellow</x:String>
<x:String>Magenta</x:String>
</controls:PickerRowEx.Items>
</controls:PickerRowEx>
</VerticalStackLayout>
如需完整代码,您可以在我的 Github Repo 中找到它
如果您喜欢这个,请投票,如果您发现它是您正在寻找的内容,请将其设置为答案。