Xamarin.Android之Spinner的简单探讨

一、前言

今天用了一下Spinner这个控件,主要是结合官网的例子来用的,不过官网的是把数据写在Strings.xml中的,

某种程度上,不是很符合我们需要的,比较多的应该都是从数据库读出来,绑定上去的。下面是官网的例子:

https://developer.xamarin.com/guides/android/user_interface/spinner/

 

二、来个简单的Demo

新建一个类 MyType.cs

 1     public class MyType 
 2     {
 3         public int TypeId { get; set; }
 4 
 5         public string TypeName { get; set; }
 6 
 7         public override string ToString()
 8         {
 9             return TypeId + "-" + TypeName;
10         }
11     }

 

再来点数据

 1     public static class DB
 2     {
 3         public static List<MyType> Types { get; private set; }
 4 
 5         static DB()
 6         {
 7             Types = new List<MyType>();
 8             Types.Add(new MyType { TypeId = 1, TypeName = "type1" });
 9             Types.Add(new MyType { TypeId = 2, TypeName = "type2" });
10             Types.Add(new MyType { TypeId = 3, TypeName = "type3" });
11             Types.Add(new MyType { TypeId = 4, TypeName = "type4" });
12         }
13     }

 

最后写个Adapter,我们自定义的Adapter都需要继承BaseAdapter

 1     public class MyTypeAdapter : BaseAdapter<MyType>
 2     {
 3         private readonly Activity _context;
 4         private readonly IList<MyType> _types;
 5 
 6         public MyTypeAdapter(Activity context, IList<MyType> types)
 7         {
 8             this._context = context;
 9             this._types = types;
10         }
11 
12         public override MyType this[int position]
13         {
14             get
15             {
16                 return this._types[position];
17             }
18         }
19 
20         public override int Count
21         {
22             get
23             {
24                 return this._types.Count;
25             }
26         }
27 
28         public override long GetItemId(int position)
29         {
30             return position;
31         }
32 
33         public override View GetView(int position, View convertView, ViewGroup parent)
34         {
35             View view = convertView;
36             if (view == null)
37             {
38                 view = this._context.LayoutInflater.Inflate(Android.Resource.Layout.SimpleListItem1, null);
39             }
40 
41             view.FindViewById<TextView>(Android.Resource.Id.Text1).Text = this._types[position].ToString();
42             return view;
43         }
44     }

 

到这里,会发现有好几个重写的方法!!这些方法是直接通过实现抽象类生成的,然后自己去完善每个方法。

既然都这样了,那就果断去看看这个BaseAdapter是干嘛的

 1     //
 2     // Summary:
 3     //     Common base class of common implementation for an Android.Widget.Adapter that
 4     //     can be /// used in both Android.Widget.ListView (by implementing the specialized
 5     //     /// Android.Widget.IListAdapter interface} and Android.Widget.Spinner (by implementing
 6     //     the /// specialized Android.Widget.ISpinnerAdapter interface.
 7     //
 8     // Type parameters:
 9     //   T:
10     //     To be added.
11     //
12     // Remarks:
13     //     ///
14     //     Common base class of common implementation for an Android.Widget.Adapter that
15     //     can be /// used in both Android.Widget.ListView (by implementing the specialized
16     //     /// Android.Widget.IListAdapter interface} and Android.Widget.Spinner (by implementing
17     //     the /// specialized Android.Widget.ISpinnerAdapter interface. ///
18     //     ///
19     //     /// /// [Android Documentation] /// ///
20     //     ///
21     [DefaultMember("Item")]
22     [Register("android/widget/BaseAdapter", DoNotGenerateAcw = true)]
23     public abstract class BaseAdapter<T> : BaseAdapter
24     {
25         [Register(".ctor", "()V", "")]
26         public BaseAdapter();
27         public BaseAdapter(IntPtr handle, JniHandleOwnership transfer);
28 
29         public abstract T this[int position] { get; }
30 
31         public override Java.Lang.Object GetItem(int position);
32     }

 

可以看到这个主要就是给ListView和Spinner用的。主要的还是它继承了BaseAdapter这个抽象类(下面的,我是去掉了注释的,方便看)

 1     public abstract class BaseAdapter : Java.Lang.Object, IListAdapter, ISpinnerAdapter, IAdapter, IJavaObject, IDisposable
 2     {
 3         public BaseAdapter();
 4         protected BaseAdapter(IntPtr javaReference, JniHandleOwnership transfer);
 5         public abstract int Count { get; }
 6         public virtual bool HasStableIds { get; }
 7         public virtual bool IsEmpty { get; }
 8         public virtual int ViewTypeCount { get; }
 9         protected override IntPtr ThresholdClass { get; }
10         protected override Type ThresholdType { get; }
11         public virtual bool AreAllItemsEnabled();
12         public virtual View GetDropDownView(int position, View convertView, ViewGroup parent);
13         public abstract Java.Lang.Object GetItem(int position);
14         public abstract long GetItemId(int position);
15         public virtual int GetItemViewType(int position);
16         public abstract View GetView(int position, View convertView, ViewGroup parent);
17         public virtual bool IsEnabled(int position);
18         public virtual void NotifyDataSetChanged();
19         public virtual void NotifyDataSetInvalidated();
20         public virtual void RegisterDataSetObserver(DataSetObserver observer);
21         public virtual void UnregisterDataSetObserver(DataSetObserver observer);
22 
23         public static class InterfaceConsts
24         {
25             public const int IgnoreItemViewType = -1;     
26             public const int NoSelection = int.MinValue;
27         }
28     }

 

可以看到,我们在自定义Adapter时,自动实现的方法,有好几个是在这里面的!!!

具体每个方法是干嘛的,就看看API吧!

https://developer.xamarin.com/api/type/Android.Widget.BaseAdapter/

 

下面来看看我们的Activity:

 1 [Activity(Label = "SpinnerActivity",MainLauncher =true)]
 2     public class SpinnerActivity : Activity
 3     {
 4         protected override void OnCreate(Bundle savedInstanceState)
 5         {
 6             base.OnCreate(savedInstanceState);
 7 
 8             // Create your application here
 9             SetContentView(Resource.Layout.spinnerlayout);
10 
11             var typesSpinner = FindViewById<Spinner>(Resource.Id.typesSpinner);
12 
13             typesSpinner.Adapter = new Models.MyTypeAdapter(this, Models.DB.Types);
14 
15             typesSpinner.ItemSelected += typesSpinner_ItemSelected;
16         }
17         
18         private void typesSpinner_ItemSelected(object sender, AdapterView.ItemSelectedEventArgs e)
19         {
20             Spinner spinner = (Spinner)sender;
21         
22             var toast = string.Format(spinner.GetItemAtPosition(e.Position).ToString());
23 
24             Toast.MakeText(this, toast, ToastLength.Long).Show();
25         }
26     }

 

很简单,下面看看效果图

     

 

但是呢,我记得在原生的开发中,下面这句应该直接是得到一个Object对象,然后通过强制转化就可以得到对应的Model

spinner.GetItemAtPosition(e.Position)

 

我试过.net下面的强制转化和object获取在转化,都没办法得到想要的效果

都是这个错。 

回想刚才的BaseAdapter类,它继承了Java.Lang.Object

所以就直接让我们的MyType去继承这个试试。可以点出来了!!

再来看看选择后的效果图:

OK,达到想要的效果了!!这样我们就可以得到任何我们想要的属性了!!不用只局限一个.ToString()方法了!

下面是MyType类和typesSpinner_ItemSelected方法

 1      public class MyType : Java.Lang.Object
 2     {
 3         public int TypeId { get; set; }
 4 
 5         public string TypeName { get; set; }
 6 
 7         public override string ToString()
 8         {
 9             return TypeId + "-" + TypeName;
10         }
11     }

 

 1         private void typesSpinner_ItemSelected(object sender, AdapterView.ItemSelectedEventArgs e)
 2         {
 3             Spinner spinner = (Spinner)sender;
 4 
 5             //var toast = string.Format(spinner.GetItemAtPosition(e.Position).ToString());
 6 
 7             var toast = (Models.MyType)spinner.GetItemAtPosition(e.Position);
 8             
 9             Toast.MakeText(this, toast.TypeName, ToastLength.Long).Show();
10         }

 

posted @ 2016-04-23 23:10  Catcher8  阅读(2124)  评论(0编辑  收藏  举报