Xamarin.Android ActionBar(その3 ドロップダウン リスト)
1 リストモード

ActionBarのNavigationModeを「ActionBarNavigationMode.List」にセットすることで、アクションバーにリスト(ドロップダウンリスト)を追加することができます。
最初にテキストのみのリストの例です。
SetListNavigationCallbacksでリストのアダプタと選択時のリスナーをセットするだけです。
[Activity(Label = "AndroidApplication1", MainLauncher = true, Icon = "@drawable/icon")] public class MainActivity : Activity, ActionBar.IOnNavigationListener{ protected override void OnCreate(Bundle bundle){ base.OnCreate(bundle); ActionBar.NavigationMode = ActionBarNavigationMode.List; //リスト表示モード SetContentView(Resource.Layout.Main); // アダプタを作成する var adapter = new ArrayAdapter(this, Android.Resource.Layout.SimpleListItem1); for (var i = 0; i < 5; i++) { adapter.Add("item_" + i); } // ナビゲーションにアダプタとコールバックをセットする ActionBar.SetListNavigationCallbacks(adapter, this); } //リスト選択時のイベント public bool OnNavigationItemSelected(int itemPosition, long itemId){ Toast.MakeText(this, itemPosition.ToString(), ToastLength.Short).Show(); return true; } }
2 独自のドロップダウンリスト
(1) ArrayAdapter

自前でアダプタを作成することで、自由なリストを作成できます。
要領は、ListViewの「表示内容のカスタマイズ」と同じです。
最初に1つのアイテムのデータ型(ListItem)を設計します。
public class ListItem{ public String Title; public Bitmap Icon; }
続いてArrayAdapter
なお、ここで GetDropDownView()をオーバーライドして、Viewを適切に設定しないと、ドロップダウン時に例外が発生します。
public class MyAdapter : ArrayAdapter<ListItem> { private readonly LayoutInflater _layoutInflater; public MyAdapter(Context context, int rid, IList<ListItem> list) : base(context, rid, list) { _layoutInflater = (LayoutInflater)context.GetSystemService(LayoutInflaterService); } public override View GetView(int position, View convertView, ViewGroup parent) { //データを取り出す var item = GetItem(position); //レイアウトファイルからViewを作成 var view = _layoutInflater.Inflate(Resource.Layout.list_item, null); var image = view.FindViewById<ImageView>(Resource.Id.imageIcon); image.SetImageBitmap(item.Icon); var textViewName = view.FindViewById<TextView>(Resource.Id.textViewTitle); textViewName.Text = item.Title; return view; } //ArrayAdapterを使用する場合は、これをoverrideして自前でviewを作成する必要がある public override View GetDropDownView(int position, View convertView, ViewGroup parent){ //convertViewがnullでも、GetViewの中で確保されるため、そのまま送っておく return GetView(position, convertView, parent); } }
1アイテム用のxmlです。
xmlは、ListViewの時と違って、適切な padding や margin を設定しないと、ドロップダウンの見た目が醜くなるので気を使う必要があります。
左図は、ちょっと詰まってしまった例で、下記は、padding等を調整したxml例です。
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="fill_parent" android:padding="10dp" > <ImageView android:id="@+id/imageIcon" android:layout_width="25dp" android:layout_height="25dp" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:layout_marginRight="5dp" /> <TextView android:id="@+id/textViewTitle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" /> </LinearLayout>
最後に使い方です。
// アダプタ用のデータ作成 var ar = new List<ListItem>(); var icEdit = BitmapFactory.DecodeResource(Resources, Android.Resource.Drawable.IcMenuEdit); ar.Add(new ListItem(){Title = "Edit", Icon = icEdit}); var icDelete = BitmapFactory.DecodeResource(Resources, Android.Resource.Drawable.IcMenuDelete); ar.Add(new ListItem(){Title = "Delete", Icon = icDelete}); var icSave = BitmapFactory.DecodeResource(Resources, Android.Resource.Drawable.IcMenuSave); ar.Add(new ListItem(){Title = "Save", Icon = icSave}); var icUpload = BitmapFactory.DecodeResource(Resources, Android.Resource.Drawable.IcMenuUpload); ar.Add(new ListItem(){Title = "Upload", Icon = icUpload}); //アダプタの作成 var myAdapter = new MyAdapter(this, ar); // ナビゲーションにアダプタとリスナーをセット ActionBar.SetListNavigationCallbacks(myAdapter, this);
(2) BaseAdapter
参考のためにArrayAdapterこちらの場合は、GetDropDownViewのoverrideは必須ではありません。
GetView()内でのデータの取り出しに、GetItem(position)を使用すると Java.Lang.Object型 になるため厄介です。
迷わず _list[position] を使用しましよう。
public class MyAdapter : BaseAdapter{ private readonly IList<ListItem> _list;//BaseAdapterの場合は、自前でListを保持する private readonly LayoutInflater _layoutInflater; public MyAdapter(Context context, IList<ListItem> list) { _list = list; _layoutInflater = LayoutInflater.FromContext(context); } public override View GetView(int position, View convertView, ViewGroup parent){ //データを取り出す //GetItem(position)でデータを取り出すとJava.Lang.Objectになるため、後々使用しづらいので //_list[position]で取り出す var item = _list[position]; var view = convertView; if (view == null){ //レイアウトファイルからViewを作成 view = _layoutInflater.Inflate(Resource.Layout.list_item, parent, false); } var textView = view.FindViewById<TextView>(Resource.Id.textViewTitle); textView.Text = item.Title; var imageView = view.FindViewById<ImageView>(Resource.Id.imageIcon); imageView.SetImageBitmap(item.Icon); return view; } //BaseAdapterがAbstractであるためoverrideが必須のメソッド public override Java.Lang.Object GetItem(int position) { return null; } //BaseAdapterがAbstractであるためoverrideが必須のメソッド public override long GetItemId(int position) { return position; } //BaseAdapterがAbstractであるためoverrideが必須のメソッド public override int Count { get { return _list.Count(); } } } }