Introduction
Xamarin.Android
is very, very good. I'm just in love with it. But as it uses GUI from Android platform itself displaying items in ListView
(ListBox
) or Spinner
(ComboBox
) can be really boring as you have to write adapters & GUI again and again. Even if all you want is to display list of string
s, you have to code it. No shortcut like:
myListBox.ItemsSource=myStringList;
Update
Initially, I omitted this part as I thought the code was self explanatory, forgetting that this is a beginner article. As Dave Kreskowiak pointed, without some explanation this was just a code dump.
Let's say we need to display a list of string
s in dialog box. To accomplish this, some steps are needed:
- XML template for single item of the list (jenerik_buyuk.axml)
- Adapter to hold and display our data (adapter_baz.cs)
- XML template for dialog box (dlg_jenerik.axml)
- Custom dialog implementation to display data (dlg_jenerik.cs)
- Finally, display our list of strings (last code block)
So I decided to share some code that I usually use. :) (no pun intended)
-
The jenerik_buyuk.axml
="1.0"="UTF-8"
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="wrap_content" android:layout_width="wrap_content"
android:padding="5dp">
<TextView android:id="@+id/txtJenerik_buyuk"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical|center_horizontal"
android:focusable="false" android:textsize="24sp">
</LinearLayout>
-
adapter_baz.cs
public class adapter_baz<T>:BaseAdapter<t>
{
internal List<t> _internalList = null;
internal LayoutInflater myInflater = null;
public int id_txtJenerik { get { return Resource.Id.txtJenerik_buyuk; } }
public int id_vwJenerik { get { return Resource.Layout.jenerik_buyuk; } }
public Func<layoutinflater,> func_onViewRequested { get; set; }
#region ctor
public adapter_baz(Context cxt, List<t> inputList)
{
myInflater = LayoutInflater.FromContext(cxt);
_internalList = inputList;
}
public adapter_baz(Context cxt)
{
myInflater = LayoutInflater.FromContext(cxt);
_internalList = null;
}
#endregion
public override T this[int position] { get { return this._internalList[position]; } }
public override int Count { get { return this._internalList.Count; } }
public override Java.Lang.Object GetItem(int position) { return position; }
public override long GetItemId(int position) { return position; }
public override View GetView(int position, View convertView, ViewGroup parent)
{
var bu = this[position];
if (func_onViewRequested != null)
return func_onViewRequested(myInflater, convertView, parent, bu);
var yen = get_GenericView(convertView);
set_GenericViewContent(yen, bu.ToString(), position);
return yen;
}
View get_GenericView(View convertView)
{
if (convertView != null)
return convertView;
return myInflater.Inflate(id_vwJenerik, null);
}
void set_GenericViewContent(View vw, string text, int pozisyon = -1)
{
TextView txt = vw.FindViewById<textview>(id_txtJenerik);
txt.Text = text;
if (pozisyon != -1)
txt.Tag = pozisyon;
}
}
-
dlg_jenerik.axml
="1.0"="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">
<ListView android:id="@+id/lv_dlg_jenerik" android:layout_width="fill_parent"
android:layout_height="fill_parent">
</LinearLayout>
-
dlg_jenerik.cs
public class dlg_jenerik<T> : Dialog
{
public adapter_baz<t> adp { get; private set; }
public Action<object> OnItemClicked { get; set; }
public dlg_jenerik(Context cxt, adapter_baz<t> gelenAdp)
{
adp = gelenAdp;
ctor_common();
}
public dlg_jenerik(Context cxt)
{
ctor_common();
}
private void ctor_common()
{
SetContentView(Resource.Layout.dlg_jenerik);
OnItemClicked = null;
var lv = (ListView)FindViewById(Resource.Id.lv_dlg_jenerik);
lv.Adapter = adp;
lv.ItemsCanFocus = false;
lv.ItemClick += new EventHandler<adapterview.itemclickeventargs>(lv_ItemClick);
}
void lv_ItemClick(object sender, AdapterView.ItemClickEventArgs e)
{
var bu = adp[e.Position];
Dismiss();
if(OnItemClicked !=null)
OnItemClicked(bu);
}
}</adapterview.itemclickeventargs>
Using the Code
Sorry for the long introduction. Now when all is ready, the usage is simple:
var list = new List<string>(){"bir","iki","uc","dort"};
var dlg = new dlg_jenerik(this,list);
dlg.OnItemClicked=(param)=>
{ HelperUI.ShowToast(param.ToString());};
dlg.Show();
Points of Interest
- You can change how each item is shown by providing your own
func_onViewRequested
in adapter_baz
- You can provide your own event handler to change what to do when item gets clicked by providing
Action<object>
in dlg_jenerik
- Logic for
LongItemClick
is the same. I was just lazy to implement it. :)
Hope these snippets help someone as some tutorial like this would have been VERY useful for me some 7-8 months ago.
What Can Be Improved?
You may decide that trivial List<T>
in adapter_baz<T> _internalList
is too trivial for you, and you need paging or data virtualization. In this case, you can use VirtualizingCollection<T>
. An excellent work by Paul McClean.
http://www.codeproject.com/Articles/34405/WPF-Data-Virtualization
This is a very neat and useful piece of code.