Szukaj…


Wprowadzenie

Każdy widok Xamarin.Forms ma towarzyszący mechanizm renderujący dla każdej platformy, który tworzy instancję kontroli rodzimej. Gdy widok jest renderowany na określonej platformie, ViewRenderer jest instancja klasy ViewRenderer .

Proces wykonania tego jest następujący:

Utwórz niestandardowy formant Xamarin.Forms.

Skorzystaj z niestandardowego formantu z Xamarin.Forms.

Utwórz niestandardowy moduł renderujący dla formantu na każdej platformie.

Wdrożenie kontroli CheckBox

W tym przykładzie zaimplementujemy niestandardowe pole wyboru dla Androida i iOS.

Tworzenie kontroli niestandardowej

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);
        }
    }
}

Zaczniemy od niestandardowego renderowania Androida, tworząc nową klasę ( CheckboxCustomRenderer ) w części naszego rozwiązania dotyczącej Android .

Kilka ważnych szczegółów, na które należy zwrócić uwagę:

  • Musimy oznaczyć najwyższą klasę za pomocą atrybutu ExportRenderer, aby renderer został zarejestrowany w Xamarin.Forms . W ten sposób Xamarin.Forms użyje tego mechanizmu renderującego, gdy będzie próbował utworzyć nasz obiekt Checkbox na Android .
  • Większość naszej pracy OnElementChanged metodą OnElementChanged , w której tworzymy instancję i konfigurujemy naszą natywną kontrolę.

Wykorzystanie kontroli niestandardowej

<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>

Tworzenie niestandardowego renderowania na każdej platformie

Proces tworzenia niestandardowej klasy mechanizmu renderującego jest następujący:

  1. Utwórz podklasę ViewRenderer<T1,T2> która renderuje formant niestandardowy. Argumentem pierwszego typu powinna być kontrola niestandardowa, dla której moduł renderujący jest, w tym przypadku CheckBox . Argumentem drugiego typu powinna być kontrola rodzima, która zaimplementuje kontrolę niestandardową.
  2. Zastąp metodę OnElementChanged , która renderuje formant niestandardowy i pisz logikę, aby go dostosować. Ta metoda jest wywoływana, gdy tworzony jest odpowiedni formant Xamarin.Forms .
  3. Dodaj atrybut ExportRenderer do niestandardowej klasy renderera, aby określić, że będzie on używany do renderowania formantu niestandardowego Xamarin.Forms . Ten atrybut służy do rejestrowania niestandardowego mechanizmu renderującego w Xamarin.Forms .

Tworzenie niestandardowego modułu renderującego dla systemu 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;
            }
        }
    }
}

Tworzenie niestandardowego modułu renderującego dla systemu iOS

Ponieważ w iOS nie ma wbudowanego pola wyboru, najpierw utworzymy CheckBoxView a następnie utworzymy renderer dla naszego pola wyboru Xamarin.Forms.

CheckBoxView jest oparty na dwóch obrazach zaznaczony_checkbox.png i unchecked_checkbox.png, więc właściwość Color zostanie zignorowana.

Widok 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);
        }
    }
}

Renderowanie niestandardowe 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;
            }
        }
    }
}

Wynik:

wprowadź opis zdjęcia tutaj wprowadź opis zdjęcia tutaj



Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow