I want to add autocomplete text-box to the list-view(custom object) in xamarin.android.
I have a listview which is being populated from string array. I would like to populate my listview using custom object.
The code below works but for string array. Any help to implement my adapter for custom object would help.
Here is the code:
Main.axml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<EditText
android:id="@+id/search"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text=""
android:hint="Enter search query" />
<Button
android:id="@+id/dosearch"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Filter list" />
<ListView
android:id="@+id/list"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</LinearLayout>
MainActivity
public class MainActivity : Activity
{
Button _button;
ListView _listview;
EditText _filterText;
FilterableAdapter _adapter;
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
// Set our view from the "main" layout resource
SetContentView (Resource.Layout.Main);
_button = FindViewById<Button> (Resource.Id.dosearch);
_listview = FindViewById<ListView> (Resource.Id.list);
_filterText = FindViewById<EditText> (Resource.Id.search);
_adapter = new FilterableAdapter (this, Android.Resource.Layout.SimpleListItem1, GetItems());
_listview.Adapter = _adapter;
_button.Click += delegate {
// filter the adapter here
_adapter.Filter.InvokeFilter(_filterText.Text);
};
_filterText.TextChanged += (object sender, Android.Text.TextChangedEventArgs e) => {
// filter on text changed
var searchTerm = _filterText.Text;
if (String.IsNullOrEmpty(searchTerm)) {
_adapter.ResetSearch();
} else {
_adapter.Filter.InvokeFilter(searchTerm);
}
};
}
string[] GetItems ()
{
string[] names = new string[] { "abc", "xyz", "yyy", "aaa" };
return names;
}
}
public class FilterableAdapter : ArrayAdapter, IFilterable
{
LayoutInflater inflater;
Filter filter;
Activity context;
public string[] AllItems;
public string[] MatchItems;
public FilterableAdapter (Activity context, int txtViewResourceId, string[] items) : base(context, txtViewResourceId, items)
{
inflater = context.LayoutInflater;
filter = new SuggestionsFilter(this);
AllItems = items;
MatchItems = items;
}
public override int Count {
get {
return MatchItems.Length;
}
}
public override Java.Lang.Object GetItem (int position)
{
return MatchItems[position];
}
public override View GetView (int position, View convertView, ViewGroup parent)
{
View view = convertView;
if (view == null)
view = inflater.Inflate(Android.Resource.Layout.SimpleDropDownItem1Line, null);
view.FindViewById<TextView>(Android.Resource.Id.Text1).Text = MatchItems[position];
return view;
}
public override Filter Filter {
get {
return filter;
}
}
public void ResetSearch() {
MatchItems = AllItems;
NotifyDataSetChanged ();
}
class SuggestionsFilter : Filter
{
readonly FilterableAdapter _adapter;
public SuggestionsFilter (FilterableAdapter adapter) : base() {
_adapter = adapter;
}
protected override Filter.FilterResults PerformFiltering (Java.Lang.ICharSequence constraint)
{
FilterResults results = new FilterResults();
if (!String.IsNullOrEmpty (constraint.ToString ())) {
var searchFor = constraint.ToString ();
Console.WriteLine ("searchFor:" + searchFor);
var matchList = new List<string> ();
var matches =
from i in _adapter.AllItems
where i.IndexOf (searchFor, StringComparison.InvariantCultureIgnoreCase) >= 0
select i;
foreach (var match in matches) {
matchList.Add (match);
}
_adapter.MatchItems = matchList.ToArray ();
Console.WriteLine ("resultCount:" + matchList.Count);
Java.Lang.Object[] matchObjects;
matchObjects = new Java.Lang.Object[matchList.Count];
for (int i = 0; i < matchList.Count; i++) {
matchObjects [i] = new Java.Lang.String (matchList [i]);
}
results.Values = matchObjects;
results.Count = matchList.Count;
} else {
_adapter.ResetSearch ();
}
return results;
}
protected override void PublishResults (Java.Lang.ICharSequence constraint, Filter.FilterResults results)
{
_adapter.NotifyDataSetChanged();
}
}
}
I would like to have my getItem method like this:
public List<ListObject> GetItems()
{
List<ListObject> model = new List<ListObject>();
model.Add(new ListObject { id = 1, Name = "abc" });
model.Add(new ListObject { id = 1, Name = "bcd" });
model.Add(new ListObject { id = 1, Name = "def" });
model.Add(new ListObject { id = 1, Name = "fgh" });
return model;
}
The main reason for doing this is I want my list to be filtered based on the data typed in edittext. And then take the selected Id and do the remaining computation.