Maui 自定义 iOS 选择器渲染器转换

问题描述 投票:0回答:1

我有一个 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);
    }
}
xamarin.ios maui .net-maui.shell
1个回答
0
投票

这是使用映射创建处理程序的一种方法。我希望这就是您正在寻找的。这不是生产就绪的代码,只是为了让您可以找到自己的方法并使其成为您自己的代码。

我们从一个 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 中找到它

如果您喜欢这个,请投票,如果您发现它是您正在寻找的内容,请将其设置为答案。

© www.soinside.com 2019 - 2024. All rights reserved.