新文章 网摘 文章 随笔 日记

Xamarin.Forms中的下拉菜单控件-第一部分

介绍

在本文中,我们将学习如何在Xamarin.Forms中创建Dropdown。默认情况下,Android平台具有称为“ Spinner”的下拉列表,但iOS平台没有像Android Spinner这样的下拉列表。在Xamarin.Forms中,我们有名为Picker的控件,我们都听说过。我们将创建一个自定义要实现的控件,例如Xamarin.Forms中的Android Spinner。

Xamarin.Forms中的下拉菜单

根据介绍,Android平台中已经有一个名为“ Spinner”的下拉控件。基本上,Xamarin.Forms控件是包装平台特定的控件。例如,Xamarin.Forms Entry是Android中EditText和iOS中UITextField的包装。我们将采用View Renderer方法,以使用一个新控件来包装特定于平台的控件。单击下面的链接,以了解有关视图渲染器的更多信息。

参考

https://docs.microsoft.com/zh-cn/xamarin/xamarin-forms/app-fundamentals/custom-renderer/view

无需过多介绍,我们将跳到本文的编码部分。

编码部分:

脚步:

我将这一部分分为以下三个步骤。

    1. 创建新的Xamarin.Forms项目。
    2. 在Xamarin.Forms .NetStandard项目中创建下拉视图。
    3. 包装微调器,用于Android Project中的下拉控件。
  1. Android平台的Dropdown及其Demo的实现。

步骤1:建立新的Xamarin.Forms专案

通过选择新建->项目->选择Xamarin Cross Platform App创建新项目,然后单击确定。
然后选择如下所示的Android和iOS平台,并将代码共享策略作为PCL或.Net Standard,然后单击确定。

步骤2:在Xamarin.Forms .NetStandard项目中创建下拉视图

在这一步中,我们将看到如何创建具有必需属性的下拉视图。

  1. 创建一个名为“ Dropdown”的类,并使用“ View”继承该Dropdown。那就是Dropdown是View的子级。
    public class Dropdown : View
    {
     //...
    }
  2. 然后,我们将创建必需的可绑定属性。首先,我们将看到下拉列表所需的所有属性和事件是什么。
    1. ItemsSource –在下拉列表中分配要填充的数据列表。
    2. SelectedIndex –标识ItemsSource中选定值的索引。
    3. ItemSelected –在下拉菜单中选择项目时执行操作的事件。
  3. 为ItemsSource创建一个可绑定属性,如下所示。
    public static readonly BindableProperty ItemsSourceProperty = BindableProperty.Create(
     propertyName: nameof(ItemsSource),
     returnType: typeof(List<string>),
     declaringType: typeof(List<string>),
     defaultValue: null);
    
    public List<string> ItemsSource
    {
     get { return (List<string>)GetValue(ItemsSourceProperty); }
     set { SetValue(ItemsSourceProperty, value); }
    }
  4. 为SelectedIndex创建一个可绑定的属性,如下所示。
    public static readonly BindableProperty SelectedIndexProperty = BindableProperty.Create(
     propertyName: nameof(SelectedIndex),
     returnType: typeof(int),
     declaringType: typeof(int),
     defaultValue: -1);
    
    public int SelectedIndex
    {
     get { return (int)GetValue(SelectedIndexProperty); }
     set { SetValue(SelectedIndexProperty, value); }
    }
  5. 创建一个用于下拉控件的自定义事件ItemSelected,然后调用该事件,如下所示。
    public event EventHandler ItemSelected;
    
    public void OnItemSelected(int pos)
    {
     ItemSelected?.Invoke(this, new ItemSelectedEventArgs() { SelectedIndex = pos });
    }
  6. 这里,ItemSelectedEventArgs是EventArgs的子级,如下所示。
    public class ItemSelectedEventArgs : EventArgs
    {
     public int SelectedIndex { get; set; }
    }
下拉视图的完整代码

在这里,我们将看到下拉视图的完整代码。

namespace XF.Ctrls
{
    public class Dropdown : View
    {
        public static readonly BindableProperty ItemsSourceProperty = BindableProperty.Create(
            propertyName: nameof(ItemsSource),
            returnType: typeof(List<string>),
            declaringType: typeof(List<string>),
            defaultValue: null);

        public List<string> ItemsSource
        {
            get { return (List<string>)GetValue(ItemsSourceProperty); }
            set { SetValue(ItemsSourceProperty, value); }
        }

        public static readonly BindableProperty SelectedIndexProperty = BindableProperty.Create(
            propertyName: nameof(SelectedIndex),
            returnType: typeof(int),
            declaringType: typeof(int),
            defaultValue: -1);

        public int SelectedIndex
        {
            get { return (int)GetValue(SelectedIndexProperty); }
            set { SetValue(SelectedIndexProperty, value); }
        }

        public event EventHandler<ItemSelectedEventArgs> ItemSelected;

        public void OnItemSelected(int pos)
        {
            ItemSelected?.Invoke(this, new ItemSelectedEventArgs() { SelectedIndex = pos });
        }
    }

    public class ItemSelectedEventArgs : EventArgs
    {
        public int SelectedIndex { get; set; }
    }
}

步骤3:在Android Project中包装Spinner以进行Dropdown控制。

在此步骤中,我们将看到“如何包装用于下拉视图的Android Spinner控件”。

  1. 在您的android客户端项目中创建一个名为“ DropdownRenderer”的类文件,并添加View Renderer,如下所示。
    public class DropdownRenderer : ViewRenderer<Dropdown, Spinner>
    {
     Spinner spinner;
     public DropdownRenderer(Context context) : base(context)
     {
    
     } 
     // ...
    }
  2. 然后覆盖方法“ OnElementChanged”和“ OnElementPropertyChanged”。在元素/控件启动时触发OnElementChanged方法。元素属性更改时,将调用OnElementPropertyChanged方法。
  3. 如下所示,使用OnElementChanged重写方法中的SetNativeControl()方法将本机控件设置为ViewRenderer。
    protected override void OnElementChanged(ElementChangedEventArgs<Dropdown> e)
    {
     base.OnElementChanged(e);
    
     if (Control == null)
     {
      spinner = new Spinner(Context);
      SetNativeControl(spinner);
     }
     //...
    }
  4. 使用数组适配器将Xamarin.Forms下拉列表中的Items Source设置为Android Spinner控件,如下所示。
    var view = e.NewElement;
    
    ArrayAdapter adapter = new ArrayAdapter(Context, Android.Resource.Layout.SimpleListItem1, view.ItemsSource);
    Control.Adapter = adapter;
    
  5. 如下所示,从所选索引设置项目的默认选择。
    if (view.SelectedIndex != -1)
    {
     Control.SetSelection(view.SelectedIndex);
    }
  6. 为微调器创建一个项目选定事件,并调用创建的下拉事件,如下所示
    // ...
    Control.ItemSelected += OnItemSelected;
    // ...
    private void OnItemSelected(object sender, AdapterView.ItemSelectedEventArgs e)
    {
     var view = Element;
     if (view != null)
     {
      view.SelectedIndex = e.Position;
      view.OnItemSelected(e.Position);
     }
    }
  7. 以相同的方式,当属性使用OnElementPropertyChanged更改时,我们将ItemsSource和SelectedIndex分配给Android Spinner,如下所示。
    protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
     var view = Element;
     if (e.PropertyName == Dropdown.ItemsSourceProperty.PropertyName)
     {
      ArrayAdapter adapter = new ArrayAdapter(Context, Android.Resource.Layout.SimpleListItem1, view.ItemsSource);
      Control.Adapter = adapter;
     }
     if (e.PropertyName == Dropdown.SelectedIndexProperty.PropertyName)
     {
      Control.SetSelection(view.SelectedIndex);
     }
     base.OnElementPropertyChanged(sender, e);
    }
  8. 在名称空间上方添加Export Renderer,以将.NetStandard项目中的下拉视图链接到Android Client Project。对于任何自定义渲染器方法来说,这都是非常重要的步骤。
    [assembly: ExportRenderer(typeof(Dropdown), typeof(DropdownRenderer))]
    namespace XF.Ctrls.Droid
下拉渲染器的完整代码

在这里,我们将看到Dropdown Renderer的完整代码。

[assembly: ExportRenderer(typeof(Dropdown), typeof(DropdownRenderer))]
namespace XF.Ctrls.Droid
{
    public class DropdownRenderer : ViewRenderer<Dropdown, Spinner>
    {
        Spinner spinner;
        public DropdownRenderer(Context context) : base(context)
        {

        }

        protected override void OnElementChanged(ElementChangedEventArgs<Dropdown> e)
        {
            base.OnElementChanged(e);

            if (Control == null)
            {
                spinner = new Spinner(Context);
                SetNativeControl(spinner);
            }

            if (e.OldElement != null)
            {
                Control.ItemSelected -= OnItemSelected;
            }
            if (e.NewElement != null)
            {
                var view = e.NewElement;

                ArrayAdapter adapter = new ArrayAdapter(Context, Android.Resource.Layout.SimpleListItem1, view.ItemsSource);
                Control.Adapter = adapter;

                if (view.SelectedIndex != -1)
                {
                    Control.SetSelection(view.SelectedIndex);
                }

                Control.ItemSelected += OnItemSelected;
            }
        }

        protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            var view = Element;
            if (e.PropertyName == Dropdown.ItemsSourceProperty.PropertyName)
            {
                ArrayAdapter adapter = new ArrayAdapter(Context, Android.Resource.Layout.SimpleListItem1, view.ItemsSource);
                Control.Adapter = adapter;
            }
            if (e.PropertyName == Dropdown.SelectedIndexProperty.PropertyName)
            {
                Control.SetSelection(view.SelectedIndex);
            }
            base.OnElementPropertyChanged(sender, e);
        }

        private void OnItemSelected(object sender, AdapterView.ItemSelectedEventArgs e)
        {
            var view = Element;
            if (view != null)
            {
                view.SelectedIndex = e.Position;
                view.OnItemSelected(e.Position);
            }
        }
    }
}

第4步:Dropdown的实现及其Android平台的演示

在这一步中,我们将看到如何在Xamarin.Forms中使用视图。

  1. 打开设计器文件,在我的情况下,打开MainPage.xaml并添加控件,如下所示。
    <local:Dropdown HorizontalOptions="FillAndExpand"
          VerticalOptions="Center"
          BackgroundColor="LawnGreen"
          x:Name="dropdown"/>
  2. 如下所示设置ItemsSource和SelectedIndex。
    dropdown.ItemsSource = Items1;
    dropdown.SelectedIndex = 1;
  3. 如下所示,将项目选择事件添加到下拉菜单中。
    public MainPage()
    {
     //...
     dropdown.ItemSelected += OnDropdownSelected;
    }
    
    private void OnDropdownSelected(object sender, ItemSelectedEventArgs e)
    {
     label.Text = Items1[e.SelectedIndex];
    }
MainPage中Dropdown的完整代码实现

在这里,我们将看到主页的完整代码。

namespace XF.Ctrls
{
    public partial class MainPage : ContentPage
    {
        List<string> Items1 = new List<string>();
        List<string> Items2 = new List<string>();
        bool IsItem1 = true;

        public MainPage()
        {
            InitializeComponent();

            for (int i = 0; i < 4; i++)
            {
                Items1.Add(i.ToString());
            }

            for (int i = 0; i < 10; i++)
            {
                Items2.Add(i.ToString());
            }

            dropdown.ItemsSource = Items1;
            dropdown.SelectedIndex = 1;
            dropdown.ItemSelected += OnDropdownSelected;
        }

        private void OnDropdownSelected(object sender, ItemSelectedEventArgs e)
        {
            label.Text = IsItem1 ? Items1[e.SelectedIndex] : Items2[e.SelectedIndex];
        }

        private void btn_Clicked(object sender, EventArgs e)
        {
            dropdown.ItemsSource = IsItem1 ? Items2 : Items1;
            dropdown.SelectedIndex = IsItem1 ? 5 : 1;
            IsItem1 = !IsItem1;
        }
    }
}

演示版

以下屏幕显示了本教程的输出,在Xamarin.Forms中具有此下拉列表非常好。

本文仅介绍了Android平台中新的下拉控件的实现。目前,我正在研究在iOS平台中创建下拉菜单之类的微调器,并将很快发布有关在iOS平台中实现下拉菜单的文章。

我的计划是创建一个下拉控件以支持所有平台,并将该控件作为标准插件提供。

下载代码

您可以从GitHub下载代码如有疑问,请随时发表评论。如果您喜欢这篇文章并且对您有用,请分享这篇文章,并在GitHub上为存储库加注星标

 
 

 

 

 

 
posted @ 2020-08-20 10:11  岭南春  阅读(971)  评论(0)    收藏  举报