问题
In Xamarin, I am having trouble with a custom adapter for a AutoCompleteTextView.
Here is my code:
private void SetupAutoCompleteTextViewWithCustomAdapter()
{
List<CustomItem> customItems = new List<CustomItem>();
CustomItem customItem = new CustomItem();
customItem.Heading = "TestHeading";
customItem.SubHeading = "TestSubHeading";
customItems.Add(customItem);
customItem = new CustomItem();
customItem.Heading = "TestHeading 2";
customItem.SubHeading = "TestSubHeading 2";
customItems.Add(customItem);
customItem = new CustomItem();
customItem.Heading = "TestHeading 3";
customItem.SubHeading = "TestSubHeading 3";
customItems.Add(customItem);
AutoCompleteTextView AutoCompleteTextViewWithCustomAdapter = (AutoCompleteTextView) FindViewById(Resource.Id.AutoCompleteTextView);
AutoCompleteTextViewWithCustomAdapter.Adapter = new CustomAdapter (this, customItems);
}
Here is my custom adapter:
public class CustomAdapter : BaseAdapter<CustomItem> {
List<CustomItem> items;
Activity context;
public CustomAdapter(Activity context, List<CustomItem> items)
: base()
{
this.context = context;
this.items = items;
}
public override long GetItemId(int position)
{
return position;
}
public override CustomItem this[int position]
{
get { return items[position]; }
}
public override int Count
{
get { return items.Count; }
}
public override View GetView(int position, View convertView, ViewGroup parent)
{
var item = items[position];
View view = convertView;
if (view == null) // no view to re-use, create new
view = context.LayoutInflater.Inflate(Resource.Layout.CustomView, null);
view.FindViewById<TextView>(Resource.Id.TextViewMapHeading).Text = item.Heading;
view.FindViewById<TextView> (Resource.Id.TextViewMapHeading).TextSize = 20;
view.FindViewById<TextView>(Resource.Id.TextViewItem).Text = item.SubHeading;
view.FindViewById<ImageView>(Resource.Id.Image).SetImageResource(item.ImageResourceId);
return view;
}
}
Here is my custom item class:
public class CustomItem
{
public string Heading { get; set; }
public string SubHeading { get; set; }
public int ImageResourceId { get; set; }
}
Here is my CustomView layout file:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="8dp">
<LinearLayout
android:id="@+id/Text"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="10dip">
<TextView
android:id="@+id/TextViewMapHeading"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textSize="28sp" />
<TextView
android:id="@+id/TextViewItem"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:autoLink="all" />
</LinearLayout>
<ImageView
android:id="@+id/Image"
android:layout_width="48dp"
android:layout_height="48dp"
android:padding="5dp"
android:src="@drawable/icon"
android:visibility="invisible"
android:layout_alignParentRight="true" />
</RelativeLayout>
Here is the error that I am getting:
java.lang.ClassCastException: simplemapdemo.CustomAdapter cannot be cast to android.widget.Filterable
Can I please have some help to get this working?
Thanks in advance
回答1:
Because the Adapter
used for AutoCompleteTextView
must be implements Filterable
interface, so modify your CustomAdapter
like following:
public class CustomAdapter extends BaseAdapter<CustomItem> implements Filterable {
ArrayFilter mFilter;
...
// please override other method in BaseAdatper as your need
...
@Override
public Filter getFilter() {
if (mFilter == null) {
mFilter = new ArrayFilter();
}
return mFilter;
}
// you can modify the custom Filter used for AutoCompleteTextView as your need
private class ArrayFilter extends Filter {
@Override
protected FilterResults performFiltering(CharSequence prefix) {
FilterResults results = new FilterResults();
if (mOriginalValues == null) {
synchronized (mLock) {
mOriginalValues = new ArrayList<T>(mObjects);
}
}
if (prefix == null || prefix.length() == 0) {
ArrayList<T> list;
synchronized (mLock) {
list = new ArrayList<T>(mOriginalValues);
}
results.values = list;
results.count = list.size();
} else {
String prefixString = prefix.toString().toLowerCase();
ArrayList<T> values;
synchronized (mLock) {
values = new ArrayList<T>(mOriginalValues);
}
final int count = values.size();
final ArrayList<T> newValues = new ArrayList<T>();
for (int i = 0; i < count; i++) {
final T value = values.get(i);
final String valueText = value.toString().toLowerCase();
// First match against the whole, non-splitted value
if (valueText.startsWith(prefixString)) {
newValues.add(value);
} else {
final String[] words = valueText.split(" ");
final int wordCount = words.length;
// Start at index 0, in case valueText starts with space(s)
for (int k = 0; k < wordCount; k++) {
if (words[k].startsWith(prefixString)) {
newValues.add(value);
break;
}
}
}
}
results.values = newValues;
results.count = newValues.size();
}
return results;
}
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
//noinspection unchecked
mObjects = (List<T>) results.values;
if (results.count > 0) {
notifyDataSetChanged();
} else {
notifyDataSetInvalidated();
}
}
}
}
You can refer to the ArrayAdapter
's source code.
来源:https://stackoverflow.com/questions/22035246/classcastexception-using-a-custom-adapter-for-an-autocompletetextview